Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix icrc7 #4

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 37 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,16 +310,16 @@ However, due to the way the Swift Decoding System works, we can not do the same

```swift
enum NamedVariant {
case one(Int8)
case two(Int16)
case three(a: Int8, b: Int16)
case one(Int8)
case two(Int16)
case three(a: Int8, b: Int16)

enum CodingKeys: String, CandidCodingKey {
case one, two, three
}
enum ThreeCodingKeys: String, CandidCodingKey {
case a, b
}
enum CodingKeys: String, CandidCodingKey {
case one, two, three
}
enum ThreeCodingKeys: String, CandidCodingKey {
case a, b
}
}
```

Expand All @@ -333,16 +333,16 @@ However, due to the way the Swift Decoding System works, we can not do the same

```swift
enum UnnamedVariant {
case anyName(Int8)
case really(Int16)
case weCanChoose(here: Int8, too: Int16)
case anyName(Int8)
case really(Int16)
case weCanChoose(here: Int8, too: Int16)

enum CodingKeys: Int, CodingKey {
case anyName, really, weCanChoose // as long as we keep the order here
}
enum WeCanChooseCodingKeys: Int, CodingKey {
case here, too // and here
}
enum CodingKeys: Int, CodingKey {
case anyName, really, weCanChoose // as long as we keep the order here
}
enum WeCanChooseCodingKeys: Int, CodingKey {
case here, too // and here
}
}
```

Expand All @@ -356,11 +356,11 @@ There are several ways to perform a request. Depending if it is a simple query o
#### Define the method you wish to call :
```swift
let method = ICPMethod(
canister: ICPSystemCanisters.ledger,
methodName: "account_balance",
arg: .record([
"account": .blob(account.accountId)
])
canister: ICPSystemCanisters.ledger,
methodName: "account_balance",
arg: .record([
"account": .blob(account.accountId)
])
)
```
#### Make the a simple query request:
Expand Down Expand Up @@ -435,6 +435,19 @@ class SimpleSigningPrincipal: ICPSigningPrincipal {
func sign(_ message: Data, domain: ICPDomainSeparator) async throws -> Data {
return try ICPCryptography.ellipticSign(message, domain: domain, with: privateKey)
}

static func fromMnemonic(_ words: [String]) throws -> SimplePrincipal {
let seed = HdWalletKit.Mnemonic.seed(mnemonic: words)!
let xPrivKey = HDExtendedKeyVersion.xprv.rawValue
let privateKey = try HDPrivateKey(seed: seed, xPrivKey: xPrivKey)
.derived(at: 44, hardened: true)
.derived(at: 223, hardened: true)
.derived(at: 0, hardened: true)
.derived(at: 0, hardened: false)
.derived(at: 0, hardened: false)
let publicKey = privateKey.publicKey(compressed: false)
return try SimplePrincipal(privateKey: privateKey.raw, uncompressedPublicKey: publicKey.raw)
}
}
```

Expand All @@ -443,4 +456,4 @@ class SimpleSigningPrincipal: ICPSigningPrincipal {
- Serialisation of recursive candid values leads to infinite loop.
- Encoding of `CandidFunctionProtocol` is not supported as there is no easy way to infer the `CandidTypes` used in the arguments and results of the function. This means that the automatic code generation will fail when calling a canister method that expects another function as input.
- Encoding of `CandidServiceProtocol` is not supported because functions can not be encoded.
- Encoding of chained optionals loses the type after one optionality level.
- Encoding of optional `Structs` can not infer the members of the struct. These are encoded as `opt empty` which should be accepted by all canisters according to Candid specifications.
4 changes: 1 addition & 3 deletions Sources/Candid/Encoding/CandidDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ private class CandidSingleValueDecodingContainer: SingleValueDecodingContainer {
}

func decode<T>(_ type: T.Type) throws -> T where T: Decodable {
guard let childValue = input.optionValue?.value else {
throw DecodingError.typeMismatch(T.self, .init(codingPath: codingPath, debugDescription: "not an optional"))
}
let childValue = input.optionValue?.value ?? input
let decoder = CandidValueDecoder(childValue, codingPath + [IntCodingKey(intValue: 0)])
return try decoder.candidDecode()
}
Expand Down
6 changes: 5 additions & 1 deletion Sources/IcpKit/ICPRequest/ICPService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ open class ICPService {
public let canister: ICPPrincipal
public let client: ICPRequestClient

public init(canister: ICPPrincipal, client: ICPRequestClient) {
public init(canister: ICPPrincipal, client: ICPRequestClient = ICPRequestClient()) {
self.canister = canister
self.client = client
}

public convenience init(_ canister: String, client: ICPRequestClient = ICPRequestClient()) throws {
self.init(canister: try ICPPrincipal(canister), client: client)
}
}
18 changes: 18 additions & 0 deletions Tests/CodeGeneratorTests/CodeGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,24 @@ let cValue: UnnamedType0 = .c(bool: true, int8: 7)
XCTAssertEqual(generated, expected)
}
}

func testIcrc7() async throws {
// GoldNFT
let service = try ICRC7.Service("io7gn-vyaaa-aaaak-qcbiq-cai")
let collectionMetadata = try await service.icrc7_collection_metadata()
let tokens = try await service.icrc7_tokens(prev: nil, take: nil)
for metadata in collectionMetadata {
print(metadata.tuple)
}
let token = tokens.first!
print(token)
let tokenMetadata = try await service.icrc7_token_metadata(token_ids: [token]).first!._1!
guard case .Text(let text) = tokenMetadata._1 else {
XCTFail()
return
}
print(text)
}
}

private class BundleDidProvider: CandidInterfaceDefinitionProvider {
Expand Down
2 changes: 1 addition & 1 deletion Tests/CodeGeneratorTests/DidFiles/ICRC7.did
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ service : {
icrc7_tx_window : () -> (opt nat) query;
icrc7_permitted_drift : () -> (opt nat) query;
icrc7_token_metadata : (token_ids : vec nat)
-> (vec opt vec record { text; Value }) query;
-> (vec record { nat; opt record { text; Value } }) query;
icrc7_owner_of : (token_ids : vec nat)
-> (vec opt Account) query;
icrc7_balance_of : (vec Account) -> (vec nat) query;
Expand Down
8 changes: 4 additions & 4 deletions Tests/CodeGeneratorTests/Generated/ICRC7.did.generated_swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ enum ICRC7 {
/// icrc7_tx_window : () -> (opt nat) query;
/// icrc7_permitted_drift : () -> (opt nat) query;
/// icrc7_token_metadata : (token_ids : vec nat)
/// -> (vec opt vec record { text; Value }) query;
/// -> (vec record { nat; opt record { text; Value } }) query;
/// icrc7_owner_of : (token_ids : vec nat)
/// -> (vec opt Account) query;
/// icrc7_balance_of : (vec Account) -> (vec nat) query;
Expand Down Expand Up @@ -256,9 +256,9 @@ enum ICRC7 {
}

/// icrc7_token_metadata : (token_ids : vec nat)
/// -> (vec opt vec record { text; Value }) query;
func icrc7_token_metadata(token_ids: [BigUInt], sender: ICPSigningPrincipal? = nil) async throws -> [[CandidTuple2<String, Value>]?] {
let caller = ICPQuery<[BigUInt], [[CandidTuple2<String, Value>]?]>(canister, "icrc7_token_metadata")
/// -> (vec record { nat; opt record { text; Value } }) query;
func icrc7_token_metadata(token_ids: [BigUInt], sender: ICPSigningPrincipal? = nil) async throws -> [CandidTuple2<BigUInt, CandidTuple2<String, Value>?>] {
let caller = ICPQuery<[BigUInt], [CandidTuple2<BigUInt, CandidTuple2<String, Value>?>]>(canister, "icrc7_token_metadata")
let response = try await caller.callMethod(token_ids, client, sender: sender)
return response
}
Expand Down
8 changes: 4 additions & 4 deletions Tests/CodeGeneratorTests/Generated/ICRC7.did.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ enum ICRC7 {
/// icrc7_tx_window : () -> (opt nat) query;
/// icrc7_permitted_drift : () -> (opt nat) query;
/// icrc7_token_metadata : (token_ids : vec nat)
/// -> (vec opt vec record { text; Value }) query;
/// -> (vec record { nat; opt record { text; Value } }) query;
/// icrc7_owner_of : (token_ids : vec nat)
/// -> (vec opt Account) query;
/// icrc7_balance_of : (vec Account) -> (vec nat) query;
Expand Down Expand Up @@ -256,9 +256,9 @@ enum ICRC7 {
}

/// icrc7_token_metadata : (token_ids : vec nat)
/// -> (vec opt vec record { text; Value }) query;
func icrc7_token_metadata(token_ids: [BigUInt], sender: ICPSigningPrincipal? = nil) async throws -> [[CandidTuple2<String, Value>]?] {
let caller = ICPQuery<[BigUInt], [[CandidTuple2<String, Value>]?]>(canister, "icrc7_token_metadata")
/// -> (vec record { nat; opt record { text; Value } }) query;
func icrc7_token_metadata(token_ids: [BigUInt], sender: ICPSigningPrincipal? = nil) async throws -> [CandidTuple2<BigUInt, CandidTuple2<String, Value>?>] {
let caller = ICPQuery<[BigUInt], [CandidTuple2<BigUInt, CandidTuple2<String, Value>?>]>(canister, "icrc7_token_metadata")
let response = try await caller.callMethod(token_ids, client, sender: sender)
return response
}
Expand Down