@twin.org/dlt-iota 0.0.3-next.5 → 0.0.3-next.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -6
- package/dist/es/index.js +2 -0
- package/dist/es/index.js.map +1 -1
- package/dist/es/iotaIdentityUtils.js +84 -0
- package/dist/es/iotaIdentityUtils.js.map +1 -0
- package/dist/es/models/IIotaControllerCapInfo.js +4 -0
- package/dist/es/models/IIotaControllerCapInfo.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/iotaIdentityUtils.d.ts +23 -0
- package/dist/types/models/IIotaControllerCapInfo.d.ts +16 -0
- package/docs/changelog.md +15 -1
- package/docs/examples.md +420 -1
- package/docs/reference/classes/Iota.md +26 -26
- package/docs/reference/classes/IotaIdentityUtils.md +65 -0
- package/docs/reference/classes/IotaSmartContractUtils.md +7 -7
- package/docs/reference/index.md +2 -0
- package/docs/reference/interfaces/IAdminCapFields.md +1 -1
- package/docs/reference/interfaces/IContractData.md +6 -6
- package/docs/reference/interfaces/IGasReservationResult.md +3 -3
- package/docs/reference/interfaces/IGasStationConfig.md +2 -2
- package/docs/reference/interfaces/IGasStationExecuteResponse.md +2 -2
- package/docs/reference/interfaces/IGasStationReserveGasResponse.md +2 -2
- package/docs/reference/interfaces/IGasStationReserveGasResult.md +3 -3
- package/docs/reference/interfaces/IIotaConfig.md +10 -52
- package/docs/reference/interfaces/IIotaControllerCapInfo.md +22 -0
- package/docs/reference/interfaces/IIotaDryRun.md +5 -5
- package/docs/reference/interfaces/IIotaResponseOptions.md +2 -8
- package/docs/reference/interfaces/IMigrationStateFields.md +2 -2
- package/docs/reference/interfaces/ISmartContractObject.md +2 -2
- package/docs/reference/variables/NetworkTypes.md +3 -3
- package/locales/en.json +6 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TWIN DLT IOTA
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This package provides utilities for integrating applications with IOTA distributed ledger capabilities, including client construction, transaction submission, sponsored transaction support, and smart contract migration helpers. It is intended for services that need a reliable and repeatable approach to ledger operations without rebuilding common primitives.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,14 +8,12 @@ DLT helpers for use with IOTA.
|
|
|
8
8
|
npm install @twin.org/dlt-iota
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Docker
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
The simplest way to set up the testing environment using our unified container:
|
|
13
|
+
To perform testing of this component it may be necessary to launch a local instance to communicate with.
|
|
16
14
|
|
|
17
15
|
```shell
|
|
18
|
-
docker run -d --name twin-
|
|
16
|
+
docker run -d --name twin-dlt-iota -p 9527:9527 -p 6379:6379 -p 9184:9184 twinfoundation/twin-gas-station-test:latest
|
|
19
17
|
```
|
|
20
18
|
|
|
21
19
|
## Examples
|
package/dist/es/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright 2024 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
3
|
export * from "./iota.js";
|
|
4
|
+
export * from "./iotaIdentityUtils.js";
|
|
4
5
|
export * from "./iotaSmartContractUtils.js";
|
|
5
6
|
export * from "./models/IAdminCapFields.js";
|
|
6
7
|
export * from "./models/IContractData.js";
|
|
@@ -10,6 +11,7 @@ export * from "./models/IGasStationExecuteResponse.js";
|
|
|
10
11
|
export * from "./models/IGasStationReserveGasResponse.js";
|
|
11
12
|
export * from "./models/IGasStationReserveGasResult.js";
|
|
12
13
|
export * from "./models/IIotaClient.js";
|
|
14
|
+
export * from "./models/IIotaControllerCapInfo.js";
|
|
13
15
|
export * from "./models/IIotaTransaction.js";
|
|
14
16
|
export * from "./models/IIotaTransactionBlockResponse.js";
|
|
15
17
|
export * from "./models/IIotaConfig.js";
|
package/dist/es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,WAAW,CAAC;AAC1B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yCAAyC,CAAC;AACxD,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./iota.js\";\nexport * from \"./iotaSmartContractUtils.js\";\nexport * from \"./models/IAdminCapFields.js\";\nexport * from \"./models/IContractData.js\";\nexport * from \"./models/IGasReservationResult.js\";\nexport * from \"./models/IGasStationConfig.js\";\nexport * from \"./models/IGasStationExecuteResponse.js\";\nexport * from \"./models/IGasStationReserveGasResponse.js\";\nexport * from \"./models/IGasStationReserveGasResult.js\";\nexport * from \"./models/IIotaClient.js\";\nexport * from \"./models/IIotaTransaction.js\";\nexport * from \"./models/IIotaTransactionBlockResponse.js\";\nexport * from \"./models/IIotaConfig.js\";\nexport * from \"./models/IIotaDryRun.js\";\nexport * from \"./models/IIotaResponseOptions.js\";\nexport * from \"./models/IMigrationStateFields.js\";\nexport * from \"./models/ISmartContractDeployments.js\";\nexport * from \"./models/ISmartContractObject.js\";\nexport * from \"./models/networkTypes.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,WAAW,CAAC;AAC1B,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yCAAyC,CAAC;AACxD,cAAc,yBAAyB,CAAC;AACxC,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./iota.js\";\nexport * from \"./iotaIdentityUtils.js\";\nexport * from \"./iotaSmartContractUtils.js\";\nexport * from \"./models/IAdminCapFields.js\";\nexport * from \"./models/IContractData.js\";\nexport * from \"./models/IGasReservationResult.js\";\nexport * from \"./models/IGasStationConfig.js\";\nexport * from \"./models/IGasStationExecuteResponse.js\";\nexport * from \"./models/IGasStationReserveGasResponse.js\";\nexport * from \"./models/IGasStationReserveGasResult.js\";\nexport * from \"./models/IIotaClient.js\";\nexport * from \"./models/IIotaControllerCapInfo.js\";\nexport * from \"./models/IIotaTransaction.js\";\nexport * from \"./models/IIotaTransactionBlockResponse.js\";\nexport * from \"./models/IIotaConfig.js\";\nexport * from \"./models/IIotaDryRun.js\";\nexport * from \"./models/IIotaResponseOptions.js\";\nexport * from \"./models/IMigrationStateFields.js\";\nexport * from \"./models/ISmartContractDeployments.js\";\nexport * from \"./models/ISmartContractObject.js\";\nexport * from \"./models/networkTypes.js\";\n"]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { IdentityClient, IdentityClientReadOnly, Jwk, JwkMemStore, KeyIdMemStore, OnChainIdentity, Storage, StorageSigner } from "@iota/identity-wasm/node/index.js";
|
|
4
|
+
import { decodeIotaPrivateKey } from "@iota/iota-sdk/cryptography";
|
|
5
|
+
import { Ed25519Keypair } from "@iota/iota-sdk/keypairs/ed25519";
|
|
6
|
+
import { Base64Url, GeneralError, Guards, Is, NotFoundError } from "@twin.org/core";
|
|
7
|
+
import { Iota } from "./iota.js";
|
|
8
|
+
/**
|
|
9
|
+
* Utility class for resolving IOTA Identity on-chain objects required by
|
|
10
|
+
* the NFT mint_with_identity() Move contract function.
|
|
11
|
+
*/
|
|
12
|
+
export class IotaIdentityUtils {
|
|
13
|
+
/**
|
|
14
|
+
* Runtime name for the class.
|
|
15
|
+
*/
|
|
16
|
+
static CLASS_NAME = "IotaIdentityUtils";
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the on-chain object IDs for an identity and its controller token.
|
|
19
|
+
* Returns the IDs needed to call mint_with_identity() on the NFT Move contract.
|
|
20
|
+
* @param identityId The DID of the identity (e.g. "did:iota:testnet:0x...").
|
|
21
|
+
* @param controllerAddress The on-chain address of the controller wallet.
|
|
22
|
+
* @param client The IOTA client instance.
|
|
23
|
+
* @returns The identity object ID and controller token object ID.
|
|
24
|
+
* @throws NotFoundError if the identity does not exist on-chain.
|
|
25
|
+
* @throws GeneralError if the identity has been deleted or the controller token is not found.
|
|
26
|
+
*/
|
|
27
|
+
static async getControllerCapInfo(identityId, controllerAddress, client) {
|
|
28
|
+
Guards.stringValue(IotaIdentityUtils.CLASS_NAME, "identityId", identityId);
|
|
29
|
+
Guards.stringValue(IotaIdentityUtils.CLASS_NAME, "controllerAddress", controllerAddress);
|
|
30
|
+
Guards.object(IotaIdentityUtils.CLASS_NAME, "client", client);
|
|
31
|
+
// Extract the Object ID from the DID — last colon-delimited segment.
|
|
32
|
+
// On-chain DIDs include the 0x prefix in the segment; the check avoids double-prefixing.
|
|
33
|
+
const idParts = identityId.split(":");
|
|
34
|
+
const lastSegment = idParts[idParts.length - 1];
|
|
35
|
+
const identityObjectId = lastSegment.startsWith("0x") ? lastSegment : `0x${lastSegment}`;
|
|
36
|
+
let onChain;
|
|
37
|
+
let controllerToken;
|
|
38
|
+
try {
|
|
39
|
+
// IIotaClient and the IotaClient expected by identity-wasm resolve from different
|
|
40
|
+
// module entry points (dist/esm vs dist/cjs). The protected `transport` field causes
|
|
41
|
+
// a structural incompatibility even though the runtime types are identical.
|
|
42
|
+
const identityClientReadOnly = await IdentityClientReadOnly.create(client);
|
|
43
|
+
// getControllerTokenForAddress requires IdentityClient even though the operation
|
|
44
|
+
// is read-only — the signer is never called, only the embedded read-only client.
|
|
45
|
+
// StorageSigner is used (rather than a plain object satisfying TransactionSigner
|
|
46
|
+
// structurally) because IdentityClient.create() validates iotaPublicKeyBytes()
|
|
47
|
+
// through an internal WASM code path that only accepts bytes from the library's
|
|
48
|
+
// own signer implementations. Plain JS objects fail with "Unsupported curve"
|
|
49
|
+
// even for valid Ed25519 keys because they take a different callback path.
|
|
50
|
+
const noOpKeypair = new Ed25519Keypair();
|
|
51
|
+
const rawPublic = noOpKeypair.getPublicKey().toRawBytes();
|
|
52
|
+
const { secretKey: rawPrivate } = decodeIotaPrivateKey(noOpKeypair.getSecretKey());
|
|
53
|
+
const noOpSigner = new StorageSigner(new Storage(new JwkMemStore(), new KeyIdMemStore()), "", new Jwk({
|
|
54
|
+
kty: "OKP" /* JwkType.Okp */,
|
|
55
|
+
crv: "Ed25519",
|
|
56
|
+
alg: "EdDSA" /* JwsAlgorithm.EdDSA */,
|
|
57
|
+
x: Base64Url.encode(rawPublic),
|
|
58
|
+
d: Base64Url.encode(rawPrivate)
|
|
59
|
+
}));
|
|
60
|
+
const identityClient = await IdentityClient.create(identityClientReadOnly, noOpSigner);
|
|
61
|
+
onChain = await OnChainIdentity.getById(identityObjectId, identityClient);
|
|
62
|
+
if (!Is.undefined(onChain) && !onChain.hasDeletedDid()) {
|
|
63
|
+
controllerToken = await onChain.getControllerTokenForAddress(controllerAddress, identityClient);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new GeneralError(IotaIdentityUtils.CLASS_NAME, "getControllerCapInfoFailed", undefined, Iota.extractPayloadError(error));
|
|
68
|
+
}
|
|
69
|
+
if (Is.undefined(onChain)) {
|
|
70
|
+
throw new NotFoundError(IotaIdentityUtils.CLASS_NAME, "identityNotFound", identityId);
|
|
71
|
+
}
|
|
72
|
+
if (onChain.hasDeletedDid()) {
|
|
73
|
+
throw new GeneralError(IotaIdentityUtils.CLASS_NAME, "identityDeleted", { identityId });
|
|
74
|
+
}
|
|
75
|
+
if (Is.undefined(controllerToken)) {
|
|
76
|
+
throw new NotFoundError(IotaIdentityUtils.CLASS_NAME, "controllerTokenNotFound", identityId);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
identityObjectId,
|
|
80
|
+
controllerCapObjectId: controllerToken.id()
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=iotaIdentityUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iotaIdentityUtils.js","sourceRoot":"","sources":["../../src/iotaIdentityUtils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tIdentityClient,\n\tIdentityClientReadOnly,\n\tJwk,\n\tJwkMemStore,\n\tJwkType,\n\tJwsAlgorithm,\n\tKeyIdMemStore,\n\tOnChainIdentity,\n\tStorage,\n\tStorageSigner\n} from \"@iota/identity-wasm/node/index.js\";\nimport { decodeIotaPrivateKey } from \"@iota/iota-sdk/cryptography\";\nimport { Ed25519Keypair } from \"@iota/iota-sdk/keypairs/ed25519\";\nimport { Base64Url, GeneralError, Guards, Is, NotFoundError } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { Iota } from \"./iota.js\";\nimport type { IIotaClient } from \"./models/IIotaClient.js\";\nimport type { IIotaControllerCapInfo } from \"./models/IIotaControllerCapInfo.js\";\n\n/**\n * Utility class for resolving IOTA Identity on-chain objects required by\n * the NFT mint_with_identity() Move contract function.\n */\nexport class IotaIdentityUtils {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<IotaIdentityUtils>();\n\n\t/**\n\t * Resolve the on-chain object IDs for an identity and its controller token.\n\t * Returns the IDs needed to call mint_with_identity() on the NFT Move contract.\n\t * @param identityId The DID of the identity (e.g. \"did:iota:testnet:0x...\").\n\t * @param controllerAddress The on-chain address of the controller wallet.\n\t * @param client The IOTA client instance.\n\t * @returns The identity object ID and controller token object ID.\n\t * @throws NotFoundError if the identity does not exist on-chain.\n\t * @throws GeneralError if the identity has been deleted or the controller token is not found.\n\t */\n\tpublic static async getControllerCapInfo(\n\t\tidentityId: string,\n\t\tcontrollerAddress: string,\n\t\tclient: IIotaClient\n\t): Promise<IIotaControllerCapInfo> {\n\t\tGuards.stringValue(IotaIdentityUtils.CLASS_NAME, nameof(identityId), identityId);\n\t\tGuards.stringValue(IotaIdentityUtils.CLASS_NAME, nameof(controllerAddress), controllerAddress);\n\t\tGuards.object(IotaIdentityUtils.CLASS_NAME, nameof(client), client);\n\n\t\t// Extract the Object ID from the DID — last colon-delimited segment.\n\t\t// On-chain DIDs include the 0x prefix in the segment; the check avoids double-prefixing.\n\t\tconst idParts = identityId.split(\":\");\n\t\tconst lastSegment = idParts[idParts.length - 1];\n\t\tconst identityObjectId = lastSegment.startsWith(\"0x\") ? lastSegment : `0x${lastSegment}`;\n\n\t\tlet onChain: OnChainIdentity | undefined;\n\t\tlet controllerToken: Awaited<ReturnType<OnChainIdentity[\"getControllerTokenForAddress\"]>>;\n\n\t\ttry {\n\t\t\t// IIotaClient and the IotaClient expected by identity-wasm resolve from different\n\t\t\t// module entry points (dist/esm vs dist/cjs). The protected `transport` field causes\n\t\t\t// a structural incompatibility even though the runtime types are identical.\n\t\t\tconst identityClientReadOnly = await IdentityClientReadOnly.create(\n\t\t\t\tclient as unknown as Parameters<(typeof IdentityClientReadOnly)[\"create\"]>[0]\n\t\t\t);\n\n\t\t\t// getControllerTokenForAddress requires IdentityClient even though the operation\n\t\t\t// is read-only — the signer is never called, only the embedded read-only client.\n\t\t\t// StorageSigner is used (rather than a plain object satisfying TransactionSigner\n\t\t\t// structurally) because IdentityClient.create() validates iotaPublicKeyBytes()\n\t\t\t// through an internal WASM code path that only accepts bytes from the library's\n\t\t\t// own signer implementations. Plain JS objects fail with \"Unsupported curve\"\n\t\t\t// even for valid Ed25519 keys because they take a different callback path.\n\t\t\tconst noOpKeypair = new Ed25519Keypair();\n\t\t\tconst rawPublic = noOpKeypair.getPublicKey().toRawBytes();\n\t\t\tconst { secretKey: rawPrivate } = decodeIotaPrivateKey(noOpKeypair.getSecretKey());\n\t\t\tconst noOpSigner = new StorageSigner(\n\t\t\t\tnew Storage(new JwkMemStore(), new KeyIdMemStore()),\n\t\t\t\t\"\",\n\t\t\t\tnew Jwk({\n\t\t\t\t\tkty: JwkType.Okp,\n\t\t\t\t\tcrv: \"Ed25519\",\n\t\t\t\t\talg: JwsAlgorithm.EdDSA,\n\t\t\t\t\tx: Base64Url.encode(rawPublic),\n\t\t\t\t\td: Base64Url.encode(rawPrivate)\n\t\t\t\t})\n\t\t\t);\n\t\t\tconst identityClient = await IdentityClient.create(identityClientReadOnly, noOpSigner);\n\n\t\t\tonChain = await OnChainIdentity.getById(identityObjectId, identityClient);\n\t\t\tif (!Is.undefined(onChain) && !onChain.hasDeletedDid()) {\n\t\t\t\tcontrollerToken = await onChain.getControllerTokenForAddress(\n\t\t\t\t\tcontrollerAddress,\n\t\t\t\t\tidentityClient\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tIotaIdentityUtils.CLASS_NAME,\n\t\t\t\t\"getControllerCapInfoFailed\",\n\t\t\t\tundefined,\n\t\t\t\tIota.extractPayloadError(error)\n\t\t\t);\n\t\t}\n\n\t\tif (Is.undefined(onChain)) {\n\t\t\tthrow new NotFoundError(IotaIdentityUtils.CLASS_NAME, \"identityNotFound\", identityId);\n\t\t}\n\n\t\tif (onChain.hasDeletedDid()) {\n\t\t\tthrow new GeneralError(IotaIdentityUtils.CLASS_NAME, \"identityDeleted\", { identityId });\n\t\t}\n\n\t\tif (Is.undefined(controllerToken)) {\n\t\t\tthrow new NotFoundError(IotaIdentityUtils.CLASS_NAME, \"controllerTokenNotFound\", identityId);\n\t\t}\n\n\t\treturn {\n\t\t\tidentityObjectId,\n\t\t\tcontrollerCapObjectId: controllerToken.id()\n\t\t};\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IIotaControllerCapInfo.js","sourceRoot":"","sources":["../../../src/models/IIotaControllerCapInfo.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * On-chain object IDs needed to call mint_with_identity() on the NFT Move contract.\n */\nexport interface IIotaControllerCapInfo {\n\t/**\n\t * The on-chain Object ID of the Identity Move object (hex string, e.g. \"0x...\").\n\t * Used as the Identity argument in mint_with_identity().\n\t */\n\tidentityObjectId: string;\n\n\t/**\n\t * The on-chain Object ID of the ControllerToken Move object (hex string, e.g. \"0x...\").\n\t * Proves that the controller address controls identityObjectId.\n\t * Used as the ControllerCap argument in mint_with_identity().\n\t */\n\tcontrollerCapObjectId: string;\n}\n"]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./iota.js";
|
|
2
|
+
export * from "./iotaIdentityUtils.js";
|
|
2
3
|
export * from "./iotaSmartContractUtils.js";
|
|
3
4
|
export * from "./models/IAdminCapFields.js";
|
|
4
5
|
export * from "./models/IContractData.js";
|
|
@@ -8,6 +9,7 @@ export * from "./models/IGasStationExecuteResponse.js";
|
|
|
8
9
|
export * from "./models/IGasStationReserveGasResponse.js";
|
|
9
10
|
export * from "./models/IGasStationReserveGasResult.js";
|
|
10
11
|
export * from "./models/IIotaClient.js";
|
|
12
|
+
export * from "./models/IIotaControllerCapInfo.js";
|
|
11
13
|
export * from "./models/IIotaTransaction.js";
|
|
12
14
|
export * from "./models/IIotaTransactionBlockResponse.js";
|
|
13
15
|
export * from "./models/IIotaConfig.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { IIotaClient } from "./models/IIotaClient.js";
|
|
2
|
+
import type { IIotaControllerCapInfo } from "./models/IIotaControllerCapInfo.js";
|
|
3
|
+
/**
|
|
4
|
+
* Utility class for resolving IOTA Identity on-chain objects required by
|
|
5
|
+
* the NFT mint_with_identity() Move contract function.
|
|
6
|
+
*/
|
|
7
|
+
export declare class IotaIdentityUtils {
|
|
8
|
+
/**
|
|
9
|
+
* Runtime name for the class.
|
|
10
|
+
*/
|
|
11
|
+
static readonly CLASS_NAME: string;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the on-chain object IDs for an identity and its controller token.
|
|
14
|
+
* Returns the IDs needed to call mint_with_identity() on the NFT Move contract.
|
|
15
|
+
* @param identityId The DID of the identity (e.g. "did:iota:testnet:0x...").
|
|
16
|
+
* @param controllerAddress The on-chain address of the controller wallet.
|
|
17
|
+
* @param client The IOTA client instance.
|
|
18
|
+
* @returns The identity object ID and controller token object ID.
|
|
19
|
+
* @throws NotFoundError if the identity does not exist on-chain.
|
|
20
|
+
* @throws GeneralError if the identity has been deleted or the controller token is not found.
|
|
21
|
+
*/
|
|
22
|
+
static getControllerCapInfo(identityId: string, controllerAddress: string, client: IIotaClient): Promise<IIotaControllerCapInfo>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On-chain object IDs needed to call mint_with_identity() on the NFT Move contract.
|
|
3
|
+
*/
|
|
4
|
+
export interface IIotaControllerCapInfo {
|
|
5
|
+
/**
|
|
6
|
+
* The on-chain Object ID of the Identity Move object (hex string, e.g. "0x...").
|
|
7
|
+
* Used as the Identity argument in mint_with_identity().
|
|
8
|
+
*/
|
|
9
|
+
identityObjectId: string;
|
|
10
|
+
/**
|
|
11
|
+
* The on-chain Object ID of the ControllerToken Move object (hex string, e.g. "0x...").
|
|
12
|
+
* Proves that the controller address controls identityObjectId.
|
|
13
|
+
* Used as the ControllerCap argument in mint_with_identity().
|
|
14
|
+
*/
|
|
15
|
+
controllerCapObjectId: string;
|
|
16
|
+
}
|
package/docs/changelog.md
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.0.3-next.7](https://github.com/twinfoundation/dlt/compare/dlt-iota-v0.0.3-next.6...dlt-iota-v0.0.3-next.7) (2026-03-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* buffer usage required for identity ([#60](https://github.com/twinfoundation/dlt/issues/60)) ([0ba7d16](https://github.com/twinfoundation/dlt/commit/0ba7d165662b0083aa2b4c1325dd8c2e65defa2e))
|
|
9
|
+
|
|
10
|
+
## [0.0.3-next.6](https://github.com/twinfoundation/dlt/compare/dlt-iota-v0.0.3-next.5...dlt-iota-v0.0.3-next.6) (2026-03-12)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* add IotaIdentityUtils to resolve IOTA identity controller cap info ([#57](https://github.com/twinfoundation/dlt/issues/57)) ([f15281a](https://github.com/twinfoundation/dlt/commit/f15281af3b2812bde5130a1813f9c0143f1462bf))
|
|
2
16
|
|
|
3
17
|
## [0.0.3-next.5](https://github.com/twinfoundation/dlt/compare/dlt-iota-v0.0.3-next.4...dlt-iota-v0.0.3-next.5) (2026-03-03)
|
|
4
18
|
|
package/docs/examples.md
CHANGED
|
@@ -1 +1,420 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DLT IOTA Examples
|
|
2
|
+
|
|
3
|
+
These snippets show practical ways to configure clients, derive addresses, post transactions, and manage contract migration flows in production-style integrations.
|
|
4
|
+
|
|
5
|
+
## Iota
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { Iota, NetworkTypes, type IIotaConfig } from '@twin.org/dlt-iota';
|
|
9
|
+
|
|
10
|
+
const config: IIotaConfig = {
|
|
11
|
+
network: NetworkTypes.Testnet,
|
|
12
|
+
clientOptions: {
|
|
13
|
+
url: 'https://api.testnet.iota.cafe'
|
|
14
|
+
},
|
|
15
|
+
inclusionTimeoutSeconds: 45
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
Iota.populateConfig(config);
|
|
19
|
+
const client = Iota.createClient(config);
|
|
20
|
+
|
|
21
|
+
console.log(config.coinType); // 4218
|
|
22
|
+
console.log(config.vaultMnemonicId); // mnemonic
|
|
23
|
+
console.log(client !== undefined); // true
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { Bip39 } from '@twin.org/crypto';
|
|
28
|
+
import { Iota } from '@twin.org/dlt-iota';
|
|
29
|
+
|
|
30
|
+
const mnemonic =
|
|
31
|
+
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
|
32
|
+
const seed = Bip39.mnemonicToSeed(mnemonic);
|
|
33
|
+
|
|
34
|
+
const addresses = Iota.getAddresses(seed, Iota.DEFAULT_COIN_TYPE, 0, 0, 3);
|
|
35
|
+
const keyPair = Iota.getKeyPair(seed, Iota.DEFAULT_COIN_TYPE, 0, 0);
|
|
36
|
+
const found = Iota.findAddress(50, Iota.DEFAULT_COIN_TYPE, seed, addresses[0]);
|
|
37
|
+
|
|
38
|
+
console.log(addresses.length); // 3
|
|
39
|
+
console.log(found.address === addresses[0]); // true
|
|
40
|
+
console.log(keyPair.publicKey.length > 0); // true
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { Converter } from '@twin.org/core';
|
|
45
|
+
import { Iota, type IIotaConfig } from '@twin.org/dlt-iota';
|
|
46
|
+
import type { IVaultConnector } from '@twin.org/vault-models';
|
|
47
|
+
|
|
48
|
+
const config: IIotaConfig = {
|
|
49
|
+
clientOptions: {
|
|
50
|
+
url: 'https://api.testnet.iota.cafe'
|
|
51
|
+
},
|
|
52
|
+
vaultMnemonicId: 'deployment-mnemonic',
|
|
53
|
+
vaultSeedId: 'deployment-seed'
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const vaultConnector: IVaultConnector = {
|
|
57
|
+
async getSecret<T>(key: string): Promise<T> {
|
|
58
|
+
if (key.endsWith('/deployment-seed')) {
|
|
59
|
+
return Converter.bytesToBase64(new Uint8Array(32).fill(7)) as T;
|
|
60
|
+
}
|
|
61
|
+
if (key.endsWith('/deployment-mnemonic')) {
|
|
62
|
+
const value =
|
|
63
|
+
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
|
64
|
+
return value as T;
|
|
65
|
+
}
|
|
66
|
+
throw new Error('Unknown key');
|
|
67
|
+
}
|
|
68
|
+
} as IVaultConnector;
|
|
69
|
+
|
|
70
|
+
const mnemonicKey = Iota.buildMnemonicKey('deployer', config.vaultMnemonicId);
|
|
71
|
+
const seedKey = Iota.buildSeedKey('deployer', config.vaultSeedId);
|
|
72
|
+
const seed = await Iota.getSeed(config, vaultConnector, 'deployer');
|
|
73
|
+
|
|
74
|
+
console.log(mnemonicKey); // deployer/deployment-mnemonic
|
|
75
|
+
console.log(seedKey); // deployer/deployment-seed
|
|
76
|
+
console.log(seed.length); // 32
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import {
|
|
81
|
+
Iota,
|
|
82
|
+
type IIotaClient,
|
|
83
|
+
type IIotaConfig,
|
|
84
|
+
type IIotaTransaction,
|
|
85
|
+
type IIotaTransactionBlockResponse
|
|
86
|
+
} from '@twin.org/dlt-iota';
|
|
87
|
+
import type { IVaultConnector } from '@twin.org/vault-models';
|
|
88
|
+
|
|
89
|
+
const config: IIotaConfig = {
|
|
90
|
+
clientOptions: {
|
|
91
|
+
url: 'https://api.testnet.iota.cafe'
|
|
92
|
+
},
|
|
93
|
+
waitForConfirmation: true
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const tx = Iota.createTransaction();
|
|
97
|
+
tx.setSender('0xabc123');
|
|
98
|
+
|
|
99
|
+
const responseOptions = {
|
|
100
|
+
waitForConfirmation: true,
|
|
101
|
+
dryRunLabel: 'transfer_iota'
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const client = {} as IIotaClient;
|
|
105
|
+
const vaultConnector = {} as IVaultConnector;
|
|
106
|
+
|
|
107
|
+
const result: IIotaTransactionBlockResponse = await Iota.prepareAndPostTransaction(
|
|
108
|
+
config,
|
|
109
|
+
vaultConnector,
|
|
110
|
+
undefined,
|
|
111
|
+
'deployer',
|
|
112
|
+
client,
|
|
113
|
+
'0xabc123',
|
|
114
|
+
tx as IIotaTransaction,
|
|
115
|
+
responseOptions
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
await Iota.waitForTransactionConfirmation(client, result.digest, config, {
|
|
119
|
+
showEffects: true,
|
|
120
|
+
showEvents: true,
|
|
121
|
+
showObjectChanges: true
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log(typeof result.digest === 'string'); // true
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import {
|
|
129
|
+
Iota,
|
|
130
|
+
type IIotaClient,
|
|
131
|
+
type IIotaConfig,
|
|
132
|
+
type IIotaTransaction,
|
|
133
|
+
type IIotaTransactionBlockResponse
|
|
134
|
+
} from '@twin.org/dlt-iota';
|
|
135
|
+
import type { IVaultConnector } from '@twin.org/vault-models';
|
|
136
|
+
|
|
137
|
+
const config: IIotaConfig = {
|
|
138
|
+
clientOptions: {
|
|
139
|
+
url: 'https://api.testnet.iota.cafe'
|
|
140
|
+
},
|
|
141
|
+
gasBudget: 80_000_000,
|
|
142
|
+
gasStation: {
|
|
143
|
+
gasStationUrl: 'https://gasstation.testnet.example',
|
|
144
|
+
gasStationAuthToken: 'replace-with-token'
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const client = {} as IIotaClient;
|
|
149
|
+
const vaultConnector = {} as IVaultConnector;
|
|
150
|
+
const tx = Iota.createTransaction();
|
|
151
|
+
|
|
152
|
+
const gasReservation = await Iota.reserveGas(config, config.gasBudget ?? 50_000_000);
|
|
153
|
+
const txBytes = new Uint8Array([1, 2, 3, 4]);
|
|
154
|
+
const userSignature = 'base64-signature';
|
|
155
|
+
|
|
156
|
+
const sponsoredResult = await Iota.executeGasStationTransaction(
|
|
157
|
+
config,
|
|
158
|
+
gasReservation.reservationId,
|
|
159
|
+
txBytes,
|
|
160
|
+
userSignature
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const finalResult: IIotaTransactionBlockResponse =
|
|
164
|
+
await Iota.executeAndConfirmGasStationTransaction(
|
|
165
|
+
config,
|
|
166
|
+
client,
|
|
167
|
+
gasReservation.reservationId,
|
|
168
|
+
txBytes,
|
|
169
|
+
userSignature,
|
|
170
|
+
{
|
|
171
|
+
waitForConfirmation: true
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const postedResult = await Iota.prepareAndPostGasStationTransaction(
|
|
176
|
+
config,
|
|
177
|
+
vaultConnector,
|
|
178
|
+
'deployer',
|
|
179
|
+
client,
|
|
180
|
+
'0xabc123',
|
|
181
|
+
tx as IIotaTransaction
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
console.log(gasReservation.reservationId > 0); // true
|
|
185
|
+
console.log(sponsoredResult.confirmedLocalExecution); // true
|
|
186
|
+
console.log(typeof finalResult.digest === 'string'); // true
|
|
187
|
+
console.log(typeof postedResult.digest === 'string'); // true
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { Iota, type IIotaClient, type IIotaConfig } from '@twin.org/dlt-iota';
|
|
192
|
+
import type { ILoggingComponent } from '@twin.org/logging-models';
|
|
193
|
+
|
|
194
|
+
const config: IIotaConfig = {
|
|
195
|
+
clientOptions: {
|
|
196
|
+
url: 'https://api.testnet.iota.cafe'
|
|
197
|
+
},
|
|
198
|
+
inclusionTimeoutSeconds: 30
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const client = {} as IIotaClient;
|
|
202
|
+
const tx = Iota.createTransaction();
|
|
203
|
+
const logging = {} as ILoggingComponent;
|
|
204
|
+
|
|
205
|
+
const packageExists = await Iota.packageExistsOnNetwork(client, '0x2');
|
|
206
|
+
const dryRun = await Iota.dryRunTransaction(client, logging, tx, '0xabc123', 'mint_token');
|
|
207
|
+
const isAbort = Iota.isAbortError(new Error('MoveAbort: abort code: 17'), 17);
|
|
208
|
+
const parsedError = Iota.extractPayloadError({ code: 'InsufficientGas' });
|
|
209
|
+
|
|
210
|
+
console.log(packageExists); // true
|
|
211
|
+
console.log(dryRun.status); // success
|
|
212
|
+
console.log(isAbort); // true
|
|
213
|
+
console.log(parsedError.name); // General
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import {
|
|
218
|
+
Iota,
|
|
219
|
+
type IIotaClient,
|
|
220
|
+
type IIotaConfig,
|
|
221
|
+
type IIotaTransactionBlockResponse
|
|
222
|
+
} from '@twin.org/dlt-iota';
|
|
223
|
+
import type { IVaultConnector } from '@twin.org/vault-models';
|
|
224
|
+
|
|
225
|
+
const config: IIotaConfig = {
|
|
226
|
+
clientOptions: {
|
|
227
|
+
url: 'https://api.testnet.iota.cafe'
|
|
228
|
+
},
|
|
229
|
+
gasStation: {
|
|
230
|
+
gasStationUrl: 'https://gasstation.testnet.example',
|
|
231
|
+
gasStationAuthToken: 'replace-with-token'
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const client = {} as IIotaClient;
|
|
236
|
+
const vaultConnector = {} as IVaultConnector;
|
|
237
|
+
|
|
238
|
+
const transferResult: IIotaTransactionBlockResponse = await Iota.prepareAndPostValueTransaction(
|
|
239
|
+
config,
|
|
240
|
+
vaultConnector,
|
|
241
|
+
undefined,
|
|
242
|
+
'deployer',
|
|
243
|
+
client,
|
|
244
|
+
'0xabc123',
|
|
245
|
+
5_000_000n,
|
|
246
|
+
'0xdef456'
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
console.log(typeof transferResult.digest === 'string'); // true
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## IotaSmartContractUtils
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import {
|
|
256
|
+
IotaSmartContractUtils,
|
|
257
|
+
NetworkTypes,
|
|
258
|
+
type IIotaConfig,
|
|
259
|
+
type ISmartContractDeployments
|
|
260
|
+
} from '@twin.org/dlt-iota';
|
|
261
|
+
import type { IotaClient } from '@iota/iota-sdk/client';
|
|
262
|
+
import type { ILoggingComponent } from '@twin.org/logging-models';
|
|
263
|
+
import type { IVaultConnector } from '@twin.org/vault-models';
|
|
264
|
+
import type { IWalletConnector } from '@twin.org/wallet-models';
|
|
265
|
+
|
|
266
|
+
const config: IIotaConfig = {
|
|
267
|
+
network: NetworkTypes.Testnet,
|
|
268
|
+
clientOptions: {
|
|
269
|
+
url: 'https://api.testnet.iota.cafe'
|
|
270
|
+
},
|
|
271
|
+
enableCostLogging: true
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const deploymentConfig: ISmartContractDeployments = {
|
|
275
|
+
testnet: {
|
|
276
|
+
packageId: '0x111',
|
|
277
|
+
deployedPackageId: '0x111',
|
|
278
|
+
migrationStateId: '0x222',
|
|
279
|
+
packageBytecode: 'base64'
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const client = {} as IotaClient;
|
|
284
|
+
const vaultConnector = {} as IVaultConnector;
|
|
285
|
+
const walletConnector = {} as IWalletConnector;
|
|
286
|
+
const logging = {} as ILoggingComponent;
|
|
287
|
+
|
|
288
|
+
await IotaSmartContractUtils.enableMigration(
|
|
289
|
+
config,
|
|
290
|
+
client,
|
|
291
|
+
vaultConnector,
|
|
292
|
+
walletConnector,
|
|
293
|
+
logging,
|
|
294
|
+
80_000_000,
|
|
295
|
+
'controller',
|
|
296
|
+
'nft',
|
|
297
|
+
'0x111',
|
|
298
|
+
deploymentConfig
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
await IotaSmartContractUtils.disableMigration(
|
|
302
|
+
config,
|
|
303
|
+
client,
|
|
304
|
+
vaultConnector,
|
|
305
|
+
walletConnector,
|
|
306
|
+
logging,
|
|
307
|
+
80_000_000,
|
|
308
|
+
'controller',
|
|
309
|
+
'nft',
|
|
310
|
+
'0x111',
|
|
311
|
+
deploymentConfig
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
console.log(IotaSmartContractUtils.CLASS_NAME); // IotaSmartContractUtils
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import {
|
|
319
|
+
IotaSmartContractUtils,
|
|
320
|
+
NetworkTypes,
|
|
321
|
+
type IIotaConfig,
|
|
322
|
+
type ISmartContractDeployments
|
|
323
|
+
} from '@twin.org/dlt-iota';
|
|
324
|
+
import type { IotaClient } from '@iota/iota-sdk/client';
|
|
325
|
+
import type { ILoggingComponent } from '@twin.org/logging-models';
|
|
326
|
+
import type { IVaultConnector } from '@twin.org/vault-models';
|
|
327
|
+
import type { IWalletConnector } from '@twin.org/wallet-models';
|
|
328
|
+
|
|
329
|
+
const config: IIotaConfig = {
|
|
330
|
+
network: NetworkTypes.Testnet,
|
|
331
|
+
clientOptions: {
|
|
332
|
+
url: 'https://api.testnet.iota.cafe'
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const deploymentConfig: ISmartContractDeployments = {
|
|
337
|
+
testnet: {
|
|
338
|
+
packageId: '0x111',
|
|
339
|
+
deployedPackageId: '0x111',
|
|
340
|
+
migrationStateId: '0x222',
|
|
341
|
+
packageBytecode: 'base64'
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const client = {} as IotaClient;
|
|
346
|
+
const vaultConnector = {} as IVaultConnector;
|
|
347
|
+
const walletConnector = {} as IWalletConnector;
|
|
348
|
+
const logging = {} as ILoggingComponent;
|
|
349
|
+
|
|
350
|
+
await IotaSmartContractUtils.migrateSmartContract(
|
|
351
|
+
config,
|
|
352
|
+
client,
|
|
353
|
+
vaultConnector,
|
|
354
|
+
walletConnector,
|
|
355
|
+
logging,
|
|
356
|
+
90_000_000,
|
|
357
|
+
'controller',
|
|
358
|
+
'0x999',
|
|
359
|
+
'nft',
|
|
360
|
+
'0x111',
|
|
361
|
+
deploymentConfig
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
const migrationActive = await IotaSmartContractUtils.isMigrationActive(
|
|
365
|
+
config,
|
|
366
|
+
client,
|
|
367
|
+
'nft',
|
|
368
|
+
'0x111',
|
|
369
|
+
deploymentConfig,
|
|
370
|
+
'controller',
|
|
371
|
+
walletConnector
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
console.log(migrationActive); // true
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
import { IotaSmartContractUtils, NetworkTypes, type IIotaConfig } from '@twin.org/dlt-iota';
|
|
379
|
+
import type { IotaClient } from '@iota/iota-sdk/client';
|
|
380
|
+
import type { IWalletConnector } from '@twin.org/wallet-models';
|
|
381
|
+
|
|
382
|
+
type ContractObjectFields = {
|
|
383
|
+
fields: {
|
|
384
|
+
version: string;
|
|
385
|
+
};
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const config: IIotaConfig = {
|
|
389
|
+
network: NetworkTypes.Testnet,
|
|
390
|
+
clientOptions: {
|
|
391
|
+
url: 'https://api.testnet.iota.cafe'
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
const client = {} as IotaClient;
|
|
396
|
+
const walletConnector = {} as IWalletConnector;
|
|
397
|
+
|
|
398
|
+
const currentVersion = await IotaSmartContractUtils.getCurrentContractVersion(
|
|
399
|
+
config,
|
|
400
|
+
client,
|
|
401
|
+
'nft',
|
|
402
|
+
'0x111',
|
|
403
|
+
'controller',
|
|
404
|
+
walletConnector
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
const isCompatible = await IotaSmartContractUtils.validateObjectVersion<ContractObjectFields>(
|
|
408
|
+
config,
|
|
409
|
+
client,
|
|
410
|
+
'nft',
|
|
411
|
+
'0x111',
|
|
412
|
+
'controller',
|
|
413
|
+
'0x777',
|
|
414
|
+
walletConnector,
|
|
415
|
+
content => Number(content.fields.version)
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
console.log(currentVersion >= 1); // true
|
|
419
|
+
console.log(isCompatible); // true
|
|
420
|
+
```
|