-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathAppUtilities.swift
142 lines (125 loc) Β· 4.04 KB
/
AppUtilities.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//
// AppUtilities.swift
//
//
// Created by Andrew Wang on 2022/7/11.
//
import Foundation
import Cadence
import BigInt
import FlowSDK
public enum AppUtilities {
public static func verifyAccountProof(
appIdentifier: String,
accountProofData: AccountProofVerifiable,
fclCryptoContract: Address?
) async throws -> Bool {
let verifyMessage = WalletUtilities.encodeAccountProof(
address: accountProofData.address,
nonce: accountProofData.nonce,
appIdentifier: appIdentifier,
includeDomainTag: false
)
var indices: [Cadence.Argument] = []
var siganature: [Cadence.Argument] = []
for signature in accountProofData.signatures {
indices.append(.int(BigInt(signature.keyId)))
siganature.append(.string(signature.signature))
}
let arguments: [Cadence.Argument] = [
.address(accountProofData.address),
.string(verifyMessage),
.array(indices),
.array(siganature),
]
let verifyScript = try getVerifySignaturesScript(
isAccountProof: true,
fclCryptoContract: fclCryptoContract
)
let result = try await fcl.query(
script: verifyScript,
arguments: arguments
)
guard case let .bool(valid) = result.value else {
throw FCLError.unexpectedResult
}
return valid
}
public static func verifyUserSignatures(
message: String,
signatures: [CompositeSignatureVerifiable],
fclCryptoContract: Address?
) async throws -> Bool {
guard let address = signatures.first?.address else {
throw FCLError.compositeSignatureInvalid
}
var indices: [Cadence.Argument] = []
var siganature: [Cadence.Argument] = []
for signature in signatures {
indices.append(.int(BigInt(signature.keyId)))
siganature.append(.string(signature.signature))
}
let arguments: [Cadence.Argument] = [
.address(Address(hexString: address)),
.string(message),
.array(indices),
.array(siganature),
]
let verifyScript = try getVerifySignaturesScript(
isAccountProof: false,
fclCryptoContract: fclCryptoContract
)
let result = try await fcl.query(
script: verifyScript,
arguments: arguments
)
guard case let .bool(valid) = result.value else {
throw FCLError.unexpectedResult
}
return valid
}
static func accountProofContractAddress(
network: Network
) throws -> Address {
switch network {
case .mainnet:
return Address(hexString: "0xb4b82a1c9d21d284")
case .testnet:
return Address(hexString: "0x74daa6f9c7ef24b1")
case .canarynet,
.sandboxnet,
.emulator,
.custom:
throw FCLError.currentNetworkNotSupported
}
}
static func getVerifySignaturesScript(
isAccountProof: Bool,
fclCryptoContract: Address?
) throws -> String {
let contractAddress: Address
if let fclCryptoContract = fclCryptoContract {
contractAddress = fclCryptoContract
} else {
contractAddress = try accountProofContractAddress(network: fcl.config.network)
}
let verifyFunction = isAccountProof
? "verifyAccountProofSignatures"
: "verifyUserSignatures"
return """
import FCLCrypto from \(contractAddress.hexStringWithPrefix)
pub fun main(
address: Address,
message: String,
keyIndices: [Int],
signatures: [String]
): Bool {
return FCLCrypto.\(verifyFunction)(
address: address,
message: message,
keyIndices: keyIndices,
signatures: signatures)
}
"""
}
}