quantumcoin 7.0.10 → 7.0.12
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-SDK.md +16 -5
- package/README.md +14 -3
- package/config.js +10 -2
- package/examples/example.js +0 -5
- package/examples/example.ts +0 -5
- package/examples/node_modules/.bin/esbuild +16 -0
- package/examples/node_modules/.bin/esbuild.cmd +17 -0
- package/examples/node_modules/.bin/esbuild.ps1 +28 -0
- package/examples/node_modules/.bin/sdkgen +16 -0
- package/examples/node_modules/.bin/sdkgen.cmd +17 -0
- package/examples/node_modules/.bin/sdkgen.ps1 +28 -0
- package/examples/node_modules/.bin/tsx +16 -0
- package/examples/node_modules/.bin/tsx.cmd +17 -0
- package/examples/node_modules/.bin/tsx.ps1 +28 -0
- package/examples/node_modules/.package-lock.json +144 -0
- package/examples/node_modules/@esbuild/win32-x64/README.md +3 -0
- package/examples/node_modules/@esbuild/win32-x64/esbuild.exe +0 -0
- package/examples/node_modules/@esbuild/win32-x64/package.json +20 -0
- package/examples/node_modules/esbuild/LICENSE.md +21 -0
- package/examples/node_modules/esbuild/README.md +3 -0
- package/examples/node_modules/esbuild/bin/esbuild +223 -0
- package/examples/node_modules/esbuild/install.js +289 -0
- package/examples/node_modules/esbuild/lib/main.d.ts +716 -0
- package/examples/node_modules/esbuild/lib/main.js +2532 -0
- package/examples/node_modules/esbuild/package.json +49 -0
- package/examples/node_modules/get-tsconfig/LICENSE +21 -0
- package/examples/node_modules/get-tsconfig/README.md +235 -0
- package/examples/node_modules/get-tsconfig/dist/index.cjs +7 -0
- package/examples/node_modules/get-tsconfig/dist/index.d.cts +2088 -0
- package/examples/node_modules/get-tsconfig/dist/index.d.mts +2088 -0
- package/examples/node_modules/get-tsconfig/dist/index.mjs +7 -0
- package/examples/node_modules/get-tsconfig/package.json +46 -0
- package/examples/node_modules/quantum-coin-js-sdk/LICENSE +21 -0
- package/examples/node_modules/quantum-coin-js-sdk/LICENSE-wasm_exec.js.txt +30 -0
- package/examples/node_modules/quantum-coin-js-sdk/README.md +1675 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/README.md +14 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/conversion-example.js +19 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-create-contract.js +396 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-encode-decode-rlp.js +225 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-event-pack-unpack.js +391 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-misc.js +101 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send-signRawTransaction.js +318 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send.js +116 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-send.js +70 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-token-pack-unpack.js +961 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet-version4.js +35 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet.js +43 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example.js +405 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +134 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/package.json +15 -0
- package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +1031 -0
- package/examples/node_modules/quantum-coin-js-sdk/index.js +3144 -0
- package/examples/node_modules/quantum-coin-js-sdk/package.json +34 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-32.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-36.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-48.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/generate-verify-vectors.js +91 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.preinit.test.js +41 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.test.js +1389 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-raw-keytype5-context-null.test.js +107 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-raw-transaction.test.js +196 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-verify.test.js +311 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/transactional.relay.test.js +131 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/transactional.rpc.test.js +103 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/verify-vectors.json +95035 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.d.ts +9 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.js +16 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasm_exec.d.ts +0 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasm_exec.js +587 -0
- package/examples/node_modules/resolve-pkg-maps/LICENSE +21 -0
- package/examples/node_modules/resolve-pkg-maps/README.md +216 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.cjs +1 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.d.cts +11 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.d.mts +11 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.mjs +1 -0
- package/examples/node_modules/resolve-pkg-maps/package.json +42 -0
- package/examples/node_modules/seed-words/.github/workflows/publish-npmjs.yaml +22 -0
- package/examples/node_modules/seed-words/BUILD.md +7 -0
- package/examples/node_modules/seed-words/LICENSE +121 -0
- package/examples/node_modules/seed-words/README.md +67 -0
- package/examples/node_modules/seed-words/dist/seedwords.d.ts +39 -0
- package/examples/node_modules/seed-words/package.json +27 -0
- package/examples/node_modules/seed-words/seedwords.js +315 -0
- package/examples/node_modules/seed-words/seedwords.txt +65536 -0
- package/examples/node_modules/seed-words/tsconfig.json +21 -0
- package/examples/node_modules/tsx/LICENSE +21 -0
- package/examples/node_modules/tsx/README.md +32 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.d.cts +35 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.d.mts +35 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/cli.cjs +54 -0
- package/examples/node_modules/tsx/dist/cli.mjs +55 -0
- package/examples/node_modules/tsx/dist/client-BQVF1NaW.mjs +1 -0
- package/examples/node_modules/tsx/dist/client-D6NvIMSC.cjs +1 -0
- package/examples/node_modules/tsx/dist/esm/api/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/esm/api/index.d.cts +35 -0
- package/examples/node_modules/tsx/dist/esm/api/index.d.mts +35 -0
- package/examples/node_modules/tsx/dist/esm/api/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/esm/index.cjs +2 -0
- package/examples/node_modules/tsx/dist/esm/index.mjs +2 -0
- package/examples/node_modules/tsx/dist/get-pipe-path-BHW2eJdv.mjs +1 -0
- package/examples/node_modules/tsx/dist/get-pipe-path-BoR10qr8.cjs +1 -0
- package/examples/node_modules/tsx/dist/index-7AaEi15b.mjs +14 -0
- package/examples/node_modules/tsx/dist/index-BWFBUo6r.cjs +1 -0
- package/examples/node_modules/tsx/dist/index-gbaejti9.mjs +1 -0
- package/examples/node_modules/tsx/dist/index-gckBtVBf.cjs +14 -0
- package/examples/node_modules/tsx/dist/lexer-DQCqS3nf.mjs +3 -0
- package/examples/node_modules/tsx/dist/lexer-DgIbo0BU.cjs +3 -0
- package/examples/node_modules/tsx/dist/loader.cjs +1 -0
- package/examples/node_modules/tsx/dist/loader.mjs +1 -0
- package/examples/node_modules/tsx/dist/node-features-_8ZFwP_x.mjs +1 -0
- package/examples/node_modules/tsx/dist/node-features-roYmp9jK.cjs +1 -0
- package/examples/node_modules/tsx/dist/package-CeBgXWuR.mjs +1 -0
- package/examples/node_modules/tsx/dist/package-Dxt5kIHw.cjs +1 -0
- package/examples/node_modules/tsx/dist/patch-repl.cjs +1 -0
- package/examples/node_modules/tsx/dist/patch-repl.mjs +1 -0
- package/examples/node_modules/tsx/dist/preflight.cjs +1 -0
- package/examples/node_modules/tsx/dist/preflight.mjs +1 -0
- package/examples/node_modules/tsx/dist/register-2sWVXuRQ.cjs +1 -0
- package/examples/node_modules/tsx/dist/register-B7jrtLTO.mjs +1 -0
- package/examples/node_modules/tsx/dist/register-CFH5oNdT.mjs +4 -0
- package/examples/node_modules/tsx/dist/register-D46fvsV_.cjs +4 -0
- package/examples/node_modules/tsx/dist/repl.cjs +3 -0
- package/examples/node_modules/tsx/dist/repl.mjs +3 -0
- package/examples/node_modules/tsx/dist/require-D4F1Lv60.cjs +1 -0
- package/examples/node_modules/tsx/dist/require-DQxpCAr4.mjs +1 -0
- package/examples/node_modules/tsx/dist/suppress-warnings.cjs +1 -0
- package/examples/node_modules/tsx/dist/suppress-warnings.mjs +1 -0
- package/examples/node_modules/tsx/dist/temporary-directory-B83uKxJF.cjs +1 -0
- package/examples/node_modules/tsx/dist/temporary-directory-CwHp0_NW.mjs +1 -0
- package/examples/node_modules/tsx/dist/types-Cxp8y2TL.d.ts +5 -0
- package/examples/node_modules/tsx/package.json +68 -0
- package/examples/offline-signing.js +0 -2
- package/examples/offline-signing.ts +0 -1
- package/examples/package-lock.json +422 -73
- package/examples/package.json +1 -1
- package/examples/wallet-offline.js +1 -9
- package/examples/wallet-offline.ts +1 -9
- package/generate-sdk.js +5 -7
- package/package.json +2 -2
- package/src/abi/interface.js +13 -7
- package/src/abi/js-abi-coder.js +23 -18
- package/src/constants.d.ts +0 -5
- package/src/constants.js +0 -7
- package/src/contract/contract-factory.js +9 -3
- package/src/contract/contract.js +9 -3
- package/src/errors/index.js +12 -0
- package/src/index.d.ts +0 -3
- package/src/providers/extra-providers.js +20 -6
- package/src/providers/json-rpc-provider.js +15 -5
- package/src/providers/provider.d.ts +0 -2
- package/src/providers/provider.js +1 -3
- package/src/utils/address.d.ts +0 -14
- package/src/utils/address.js +12 -49
- package/src/utils/hashing.d.ts +0 -6
- package/src/utils/hashing.js +8 -23
- package/src/utils/index.d.ts +0 -3
- package/src/utils/rlp.js +7 -4
- package/src/wallet/wallet.d.ts +7 -13
- package/src/wallet/wallet.js +136 -97
- package/test/security/malformed-input.test.js +295 -1
- package/test/unit/address-wallet.test.js +329 -129
- package/test/unit/address-wallet.test.ts +328 -128
- package/test/unit/hashing.test.js +0 -11
- package/test/unit/hashing.test.ts +0 -11
- package/test/unit/providers.test.js +3 -1
- package/test/unit/providers.test.ts +3 -1
- package/SPEC.md +0 -3845
|
@@ -0,0 +1,3144 @@
|
|
|
1
|
+
//index.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Quantum Coin Blockchain SDK
|
|
5
|
+
* @module quantum-coin-js-sdk
|
|
6
|
+
* @description Quantum Coin JS SDK provides low level functionality to interact with the Quantum Coin Blockchain.
|
|
7
|
+
* {@link https://github.com/quantumcoinproject/quantum-coin-js-sdk/tree/main/example|Example Project}
|
|
8
|
+
* @example
|
|
9
|
+
*
|
|
10
|
+
* Requires Node.js version v20.18.1 or higher
|
|
11
|
+
*
|
|
12
|
+
* Installation:
|
|
13
|
+
* npm install quantum-coin-js-sdk --save
|
|
14
|
+
*
|
|
15
|
+
* //Adding reference:
|
|
16
|
+
* var qcsdk = require('quantum-coin-js-sdk');
|
|
17
|
+
*
|
|
18
|
+
* //Example initialization with defaults for mainnet
|
|
19
|
+
* //Initialize the SDK first before invoking any other function
|
|
20
|
+
* qcsdk.initialize(null).then((initResult) => {
|
|
21
|
+
*
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* //Example initialization with specific values
|
|
25
|
+
* //Initialize the SDK first before invoking any other function
|
|
26
|
+
* var clientConfigVal = new qcsdk.Config("https://sdk.readrelay.quantumcoinapi.com", "https://sdk.writerelay.quantumcoinapi.com", 123123, "", ""); //Initialization with Mainnet Config (Block Explorer: https://QuantumScan.com)
|
|
27
|
+
* qcsdk.initialize(clientConfigVal).then((initResult) => {
|
|
28
|
+
*
|
|
29
|
+
* }
|
|
30
|
+
* Example Project: https://github.com/quantumcoinproject/quantum-coin-js-sdk/tree/main/example
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
var wasmexec = require('./wasm_exec');
|
|
35
|
+
var wasmBase64 = require('./wasmBase64');
|
|
36
|
+
const crypto = require("crypto");
|
|
37
|
+
var seedwords = require('seed-words');
|
|
38
|
+
|
|
39
|
+
var config = null;
|
|
40
|
+
var isInitialized = false;
|
|
41
|
+
/** CIRCL WASM namespace (set after InitAccountsWebAssembly). Use getCircl() for access. */
|
|
42
|
+
var circl = null;
|
|
43
|
+
const DEFAULT_GAS = 21000;
|
|
44
|
+
const API_KEY_HEADER_NAME = "X-API-KEY";
|
|
45
|
+
const REQUEST_ID_HEADER_NAME = "X-REQUEST-ID";
|
|
46
|
+
|
|
47
|
+
// Key type and seed constants (CIRCL migration; see pqc-circl-migration.md)
|
|
48
|
+
const KEY_TYPE_HYBRIDEDMLDSASLHDSA = 3;
|
|
49
|
+
const KEY_TYPE_HYBRIDEDMLDSASLHDSA5 = 5;
|
|
50
|
+
const SEED_WORD_LIST_LENGTH_HYBRIDEDS = 48;
|
|
51
|
+
const SEED_WORD_LIST_LENGTH_HYBRIDEDMLDSASLHDSA5 = 36;
|
|
52
|
+
const SEED_WORD_LIST_LENGTH_HYBRIDEDMLDSASLHDSA = 32;
|
|
53
|
+
const BASE_SEED_BYTES_HYBRIDEDS = 96;
|
|
54
|
+
const BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA5 = 72;
|
|
55
|
+
const BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA = 64;
|
|
56
|
+
const MIN_PASSPHRASE_LENGTH = 12;
|
|
57
|
+
const INVALID_KEY_TYPE = -1001;
|
|
58
|
+
const CIRCL_CRYPTO_FAILURE = -1002;
|
|
59
|
+
const EXPECTED_WASM_SHA256 = "bcab6389db37af9cc6538fb54a872f416131392d3ad5ea23a0969d8aac3b1c85";
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @class
|
|
63
|
+
* @constructor
|
|
64
|
+
* @public
|
|
65
|
+
* @classdesc This is the configuration class required to initialize and interact with Quantum Coin blockchain
|
|
66
|
+
*/
|
|
67
|
+
class Config {
|
|
68
|
+
/**
|
|
69
|
+
* Creates a config class
|
|
70
|
+
* @param {string} readUrl - The Read API URL pointing to a read relay. See https://github.com/quantumcoinproject/quantum-coin-go/tree/dogep/relay. The following URLs are community maintained. Please use your own relay service. Mainnet: https://sdk.readrelay.quantumcoinapi.com
|
|
71
|
+
* @param {string} writeUrl - The Write API URL pointing to a write relay. See https://github.com/quantumcoinproject/quantum-coin-go/tree/dogep/relay. The following URLs are community maintained. Please use your own relay service. Mainnet: https://sdk.writerelay.quantumcoinapi.com
|
|
72
|
+
* @param {number} chainId - The chain id of the blockchain. Mainnet chainId is 123123. Testnet T4 chainId is 310324.
|
|
73
|
+
* @param {string} readApiKey - Optional parameter if authorization is enabled for the relay service. API Key for authorization. Defaults to null which indicates no authorization.
|
|
74
|
+
* @param {string} writeApiKey - Optional parameter if authorization is enabled for the relay service. API Key for authorization. Defaults to null which indicates no authorization.
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
constructor(readUrl, writeUrl, chainId, readApiKey, writeApiKey) {
|
|
78
|
+
/**
|
|
79
|
+
* The Read API URL pointing to a read relay. See https://github.com/quantumcoinproject/quantum-coin-go/tree/dogep/relay
|
|
80
|
+
* @type {string}
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
this.readUrl = readUrl;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The Read API URL pointing to a read relay. See https://github.com/quantumcoinproject/quantum-coin-go/tree/dogep/relay
|
|
87
|
+
* @type {string}
|
|
88
|
+
* @public
|
|
89
|
+
*/
|
|
90
|
+
this.writeUrl = writeUrl;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The chain id of the blockchain. Mainnet chainId is 123123. Testnet T4 chainId is 310324.
|
|
94
|
+
* @type {number}
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
this.chainId = chainId;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* API Key for authorization if authorization is enabled for the relay service. Defaults to null which indicates no authorization.
|
|
101
|
+
* @type {string}
|
|
102
|
+
* @public
|
|
103
|
+
*/
|
|
104
|
+
this.readApiKey = readApiKey;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* API Key for authorization if authorization is enabled for the relay service. Defaults to null which indicates no authorization.
|
|
108
|
+
* @type {string}
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
111
|
+
this.writeApiKey = writeApiKey;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @class
|
|
117
|
+
* @constructor
|
|
118
|
+
* @public
|
|
119
|
+
* @classdesc This class represents a Wallet. Use the verifyWallet function to verify if a wallet is valid. Verifying the wallet is highly recommended, especially if it comes from an untrusted source. For more details on the underlying cryptography of the Wallet, see https://github.com/QuantumCoinProject/hybrid-pqc
|
|
120
|
+
*/
|
|
121
|
+
class Wallet {
|
|
122
|
+
/**
|
|
123
|
+
* Creates a Wallet class. The constructor does not verify the wallet. To verify a wallet, call the verifyWallet function explicitly.
|
|
124
|
+
* @param {string} address - Address of the wallet
|
|
125
|
+
* @param {number[]} privateKey - Private Key byte array of the wallet
|
|
126
|
+
* @param {number[]} publicKey - Public Key byte array of the wallet
|
|
127
|
+
* @param {Uint8Array|number[]|null} [preExpansionSeed=null] - Optional pre-expansion seed bytes. Non-null only for seed-derived wallets.
|
|
128
|
+
*/
|
|
129
|
+
constructor(address, privateKey, publicKey, preExpansionSeed) {
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Address of the wallet. Is 66 bytes in length including 0x (if the wallet is valid).
|
|
133
|
+
* @type {string}
|
|
134
|
+
* @public
|
|
135
|
+
*/
|
|
136
|
+
this.address = address;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Private Key byte array of the wallet. Is 4064 bytes in length (if the wallet is valid).
|
|
140
|
+
* @type {number[]}
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
this.privateKey = privateKey;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Public Key byte array of the wallet. Is 1408 bytes in length (if the wallet is valid).
|
|
147
|
+
* @type {number[]}
|
|
148
|
+
* @public
|
|
149
|
+
*/
|
|
150
|
+
this.publicKey = publicKey;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Pre-expansion seed bytes. Can be null if the wallet was not created from a seed.
|
|
154
|
+
* @type {Uint8Array|number[]|null}
|
|
155
|
+
* @public
|
|
156
|
+
*/
|
|
157
|
+
this.preExpansionSeed = preExpansionSeed || null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @class
|
|
163
|
+
* @constructor
|
|
164
|
+
* @public
|
|
165
|
+
* @classdesc This class represents a Block.
|
|
166
|
+
*/
|
|
167
|
+
class BlockDetails {
|
|
168
|
+
constructor(blockNumber) {
|
|
169
|
+
/**
|
|
170
|
+
* Block Number of the block
|
|
171
|
+
* @type {number}
|
|
172
|
+
* @public
|
|
173
|
+
*/
|
|
174
|
+
this.blockNumber = blockNumber;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @class
|
|
180
|
+
* @constructor
|
|
181
|
+
* @public
|
|
182
|
+
* @classdesc This class represents a result from invoking the getLatestBlock function.
|
|
183
|
+
*/
|
|
184
|
+
class LatestBlockDetailsResult {
|
|
185
|
+
constructor(resultCode, blockDetails, response, requestId, err) {
|
|
186
|
+
/**
|
|
187
|
+
* Represents the result of the operation. A value of 0 represents that the operation succeeded. Any other value indicates the operation failed. See the result code section for more details.
|
|
188
|
+
* @type {number}
|
|
189
|
+
* @public
|
|
190
|
+
*/
|
|
191
|
+
this.resultCode = resultCode;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* An object of type BlockDetails representing the block. This value is null if the value of resultCode is not 0.
|
|
195
|
+
* @type {BlockDetails}
|
|
196
|
+
* @public
|
|
197
|
+
*/
|
|
198
|
+
this.blockDetails = blockDetails;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* An object of representing the raw Response returned by the service. For details, see https://developer.mozilla.org/en-US/docs/Web/API/Response. This value can be null if the value of resultCode is not 0.
|
|
202
|
+
* @type {Object}
|
|
203
|
+
* @public
|
|
204
|
+
*/
|
|
205
|
+
this.response = response;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* An unique id to represent the request. This can be null if request failed before it could be sent.
|
|
209
|
+
* @type {string}
|
|
210
|
+
* @public
|
|
211
|
+
*/
|
|
212
|
+
this.requestId = requestId;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* An error object if the operation resulted in an error and there was no response. This property is defined only if the resultCode is -10000.
|
|
216
|
+
* @type {Error}
|
|
217
|
+
* @public
|
|
218
|
+
*/
|
|
219
|
+
this.err = err;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @class
|
|
225
|
+
* @constructor
|
|
226
|
+
* @public
|
|
227
|
+
* @classdesc This class represents an Account.
|
|
228
|
+
*/
|
|
229
|
+
class AccountDetails {
|
|
230
|
+
constructor(address, balance, nonce, blockNumber) {
|
|
231
|
+
/**
|
|
232
|
+
* Address of the wallet. Is 66 bytes in length including 0x.
|
|
233
|
+
* @type {string}
|
|
234
|
+
* @public
|
|
235
|
+
*/
|
|
236
|
+
this.address = address;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Balance of the account in wei. To convert this to ethers, see https://docs.ethers.org/v4/api-utils.html#ether-strings-and-wei
|
|
240
|
+
* @type {string}
|
|
241
|
+
* @public
|
|
242
|
+
*/
|
|
243
|
+
this.balance = balance;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* A monotonically increasing number representing the nonce of the account. After each transaction from the account that gets registered in the blockchain, the nonce increases by 1.
|
|
247
|
+
* @type {number}
|
|
248
|
+
* @public
|
|
249
|
+
*/
|
|
250
|
+
this.nonce = nonce;
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* The block number as of which the Account details was retrieved.
|
|
254
|
+
* @type {number}
|
|
255
|
+
* @public
|
|
256
|
+
*/
|
|
257
|
+
this.blockNumber = blockNumber;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* @class
|
|
263
|
+
* @constructor
|
|
264
|
+
* @public
|
|
265
|
+
* @classdesc This class represents a result from invoking the getAccountDetails function.
|
|
266
|
+
*/
|
|
267
|
+
class AccountDetailsResult {
|
|
268
|
+
constructor(resultCode, accountDetails, response, requestId, err) {
|
|
269
|
+
/**
|
|
270
|
+
* Represents the result of the operation. A value of 0 represents that the operation succeeded. Any other value indicates the operation failed. See the result code section for more details.
|
|
271
|
+
* @type {number}
|
|
272
|
+
* @public
|
|
273
|
+
*/
|
|
274
|
+
this.resultCode = resultCode;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* An object of type AccountDetails representing the block. This value is null if the value of resultCode is not 0.
|
|
278
|
+
* @type {AccountDetails}
|
|
279
|
+
* @public
|
|
280
|
+
*/
|
|
281
|
+
this.accountDetails = accountDetails;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* An object of representing the raw Response returned by the service. For details, see https://developer.mozilla.org/en-US/docs/Web/API/Response. This value can be null if the value of resultCode is not 0.
|
|
285
|
+
* @type {Object}
|
|
286
|
+
* @public
|
|
287
|
+
*/
|
|
288
|
+
this.response = response;
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* An unique id to represent the request. This can be null if request failed before it could be sent.
|
|
292
|
+
* @type {string}
|
|
293
|
+
* @public
|
|
294
|
+
*/
|
|
295
|
+
this.requestId = requestId;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* An error object if the operation resulted in an error and there was no response. This property is defined only if the resultCode is -10000.
|
|
299
|
+
* @type {Error}
|
|
300
|
+
* @public
|
|
301
|
+
*/
|
|
302
|
+
this.err = err;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* @class
|
|
308
|
+
* @constructor
|
|
309
|
+
* @public
|
|
310
|
+
* @classdesc This class represents a result from invoking the signSendCoinTransaction function.
|
|
311
|
+
*/
|
|
312
|
+
class SignResult {
|
|
313
|
+
constructor(resultCode, txnHash, txnData) {
|
|
314
|
+
/**
|
|
315
|
+
* Represents the result of the operation. A value of 0 represents that the operation succeeded. Any other value indicates the operation failed. See the result code section for more details.
|
|
316
|
+
* @type {number}
|
|
317
|
+
* @public
|
|
318
|
+
*/
|
|
319
|
+
this.resultCode = resultCode;
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Hash of the Transaction, to uniquely identify it. Is 66 bytes in length including 0x. This value is null if the value of resultCode is not 0.
|
|
323
|
+
* @type {string}
|
|
324
|
+
* @public
|
|
325
|
+
*/
|
|
326
|
+
this.txnHash = txnHash;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* A payload representing the signed transaction.
|
|
330
|
+
* To actually send a transaction, this payload can then be taken to to a different device that is connected to the blockchain relay and then sent using the postTransaction function.
|
|
331
|
+
* This value is null if the value of resultCode is not 0.
|
|
332
|
+
* @type {string}
|
|
333
|
+
* @public
|
|
334
|
+
*/
|
|
335
|
+
this.txnData = txnData;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* @class
|
|
341
|
+
* @constructor
|
|
342
|
+
* @public
|
|
343
|
+
* @classdesc This class represents a result from invoking the sendCoins function.
|
|
344
|
+
*/
|
|
345
|
+
class SendResult {
|
|
346
|
+
constructor(resultCode, txnHash, response, requestId, err) {
|
|
347
|
+
/**
|
|
348
|
+
* Represents the result of the operation. A value of 0 represents that the operation succeeded. Any other value indicates the operation failed. See the result code section for more details.
|
|
349
|
+
* @type {number}
|
|
350
|
+
* @public
|
|
351
|
+
*/
|
|
352
|
+
this.resultCode = resultCode;
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Hash of the Transaction, to uniquely identify it. Is 66 bytes in length including 0x. This value is null if the value of resultCode is not 0.
|
|
356
|
+
* @type {string}
|
|
357
|
+
* @public
|
|
358
|
+
*/
|
|
359
|
+
this.txnHash = txnHash;
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* An object of representing the raw Response returned by the service. For details, see https://developer.mozilla.org/en-US/docs/Web/API/Response. This value can be null if the value of resultCode is not 0.
|
|
363
|
+
* @type {Object}
|
|
364
|
+
* @public
|
|
365
|
+
*/
|
|
366
|
+
this.response = response;
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* An unique id to represent the request. This can be null if request failed before it could be sent.
|
|
370
|
+
* @type {string}
|
|
371
|
+
* @public
|
|
372
|
+
*/
|
|
373
|
+
this.requestId = requestId;
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* An error object if the operation resulted in an error and there was no response. This property is defined only if the resultCode is -10000.
|
|
377
|
+
* @type {Error}
|
|
378
|
+
* @public
|
|
379
|
+
*/
|
|
380
|
+
this.err = err;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* @class
|
|
386
|
+
* @constructor
|
|
387
|
+
* @public
|
|
388
|
+
* @classdesc This class represents a Receipt of a transaction that is registered in the blockchain. The transactionReceipt field can be null unless the transaction is registered with the blockchain.
|
|
389
|
+
* While the transaction is pending, this field will be null. You should consider the transaction as succeeded only if the status field's value is 0x1 (success).
|
|
390
|
+
*/
|
|
391
|
+
class TransactionReceipt {
|
|
392
|
+
constructor() {
|
|
393
|
+
/**
|
|
394
|
+
* A hexadecimal string representing the total amount of gas used when this transaction was executed in the block.
|
|
395
|
+
* @type {string}
|
|
396
|
+
* @public
|
|
397
|
+
*/
|
|
398
|
+
this.cumulativeGasUsed = null;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* A hexadecimal string representing the sum of the base fee and tip paid per unit of gas.
|
|
402
|
+
* @type {string}
|
|
403
|
+
* @public
|
|
404
|
+
*/
|
|
405
|
+
this.effectiveGasPrice = null;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* A hexadecimal string representing the amount of gas used by this specific transaction alone.
|
|
409
|
+
* @type {string}
|
|
410
|
+
* @public
|
|
411
|
+
*/
|
|
412
|
+
this.gasUsed = null;
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* A hexadecimal string representing either 0x1 (success) or 0x0 (failure). Failed transactions can also incur gas fee. You should consider the transaction as succeeded only if the status value is 0x1 (success).
|
|
416
|
+
* @type {string}
|
|
417
|
+
* @public
|
|
418
|
+
*/
|
|
419
|
+
this.status = null;
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Hash of the Transaction, to uniquely identify it. Is 66 bytes in length including 0x.
|
|
423
|
+
* @type {string}
|
|
424
|
+
* @public
|
|
425
|
+
*/
|
|
426
|
+
this.hash = null;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* A hexadecimal string representing the transaction type. 0x0 is DefaultFeeTxType.
|
|
430
|
+
* @type {string}
|
|
431
|
+
* @public
|
|
432
|
+
*/
|
|
433
|
+
this.type = null;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @class
|
|
439
|
+
* @constructor
|
|
440
|
+
* @public
|
|
441
|
+
* @classdesc This class represents details of a transaction. You should consider the transaction as succeeded only if the status field of the receipt object is 0x1 (success).
|
|
442
|
+
*/
|
|
443
|
+
class TransactionDetails {
|
|
444
|
+
constructor() {
|
|
445
|
+
/**
|
|
446
|
+
* A hexadecimal string representing the hash of the block that registered the transaction. This field can be null if the transaction was not registered in the blockchain.
|
|
447
|
+
* @type {string}
|
|
448
|
+
* @public
|
|
449
|
+
*/
|
|
450
|
+
this.blockHash = null;
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* The number of the block that registered the transaction. This field can be null if the transaction was not registered in the blockchain.
|
|
454
|
+
* @type {number}
|
|
455
|
+
* @public
|
|
456
|
+
*/
|
|
457
|
+
this.blockNumber = null;
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* A 66 character hexadecimal string representing the address the transaction is sent from.
|
|
461
|
+
* @type {string}
|
|
462
|
+
* @public
|
|
463
|
+
*/
|
|
464
|
+
this.from = null;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* A hexadecimal string representing the gas provided for the transaction execution.
|
|
468
|
+
* @type {string}
|
|
469
|
+
* @public
|
|
470
|
+
*/
|
|
471
|
+
this.gas = null;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* A hexadecimal string representing the gasPrice used for each paid gas, in Wei.
|
|
475
|
+
* @type {string}
|
|
476
|
+
* @public
|
|
477
|
+
*/
|
|
478
|
+
this.gasPrice = null;
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* A 66 character hexadecimal string representing the hash of the transaction.
|
|
482
|
+
* @type {string}
|
|
483
|
+
* @public
|
|
484
|
+
*/
|
|
485
|
+
this.hash = null;
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* A hexadecimal string representing the compiled code of a contract OR the hash of the invoked method signature and encoded parameters.
|
|
489
|
+
* @type {string}
|
|
490
|
+
* @public
|
|
491
|
+
*/
|
|
492
|
+
this.input = null;
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* A monotonically increasing number representing the nonce of the account. After each transaction from the account that gets registered in the blockchain, the nonce increases by 1.
|
|
496
|
+
* @type {number}
|
|
497
|
+
* @public
|
|
498
|
+
*/
|
|
499
|
+
this.nonce = null;
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* A 66 character hexadecimal string representing address the transaction is directed to.
|
|
503
|
+
* @type {string}
|
|
504
|
+
* @public
|
|
505
|
+
*/
|
|
506
|
+
this.to = null;
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* A hexadecimal string representing the value sent with this transaction. The value can be 0 for smart contract transactions, since it only represents the number of coins sent.
|
|
510
|
+
* @type {string}
|
|
511
|
+
* @public
|
|
512
|
+
*/
|
|
513
|
+
this.value = null;
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* The receipt of the transaction. This field will be null while the transaction is pending (not yet registered in the blockchain).
|
|
517
|
+
* @type {TransactionReceipt}
|
|
518
|
+
* @public
|
|
519
|
+
*/
|
|
520
|
+
this.receipt = null;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* @class
|
|
527
|
+
* @constructor
|
|
528
|
+
* @public
|
|
529
|
+
* @classdesc This class represents a result from invoking the getTransactionDetails function. If transactions get discarded by the blockchain, for reasons such as due to lower than minimum gas fees or invalid nonce, the resultCode will always contain a non-zero value (failure).
|
|
530
|
+
*/
|
|
531
|
+
class TransactionDetailsResult {
|
|
532
|
+
constructor(resultCode, transactionDetails, response, requestId, err) {
|
|
533
|
+
/**
|
|
534
|
+
* Represents the result of the operation. A value of 0 represents that the operation succeeded. Any other value indicates the operation failed. See the result code section for more details.
|
|
535
|
+
* @type {number}
|
|
536
|
+
* @public
|
|
537
|
+
*/
|
|
538
|
+
|
|
539
|
+
this.resultCode = resultCode;
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* An object of type TransactionDetails representing the transaction. This value is null if the value of resultCode is not 0.
|
|
543
|
+
* @type {TransactionDetails}
|
|
544
|
+
* @public
|
|
545
|
+
*/
|
|
546
|
+
this.transactionDetails = transactionDetails;
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* An object of representing the raw Response returned by the service. For details, see https://developer.mozilla.org/en-US/docs/Web/API/Response. This value can be null if the value of resultCode is not 0.
|
|
550
|
+
* @type {Object}
|
|
551
|
+
* @public
|
|
552
|
+
*/
|
|
553
|
+
this.response = response;
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* An unique id to represent the request. This can be null if request failed before it could be sent.
|
|
557
|
+
* @type {string}
|
|
558
|
+
* @public
|
|
559
|
+
*/
|
|
560
|
+
this.requestId = requestId;
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* An error object if the operation resulted in an error and there was no response. This property is defined only if the resultCode is -10000.
|
|
564
|
+
* @type {Error}
|
|
565
|
+
* @public
|
|
566
|
+
*/
|
|
567
|
+
this.err = err;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* @class
|
|
573
|
+
* @constructor
|
|
574
|
+
* @public
|
|
575
|
+
* @classdesc This class represents a transaction of an account. You should consider the transaction as succeeded only if the status field is 0x1 (success).
|
|
576
|
+
*/
|
|
577
|
+
class AccountTransactionCompact {
|
|
578
|
+
constructor() {
|
|
579
|
+
/**
|
|
580
|
+
* The number of the block that registered the transaction. This field can be null if the transaction was not registered in the blockchain.
|
|
581
|
+
* @type {number}
|
|
582
|
+
* @public
|
|
583
|
+
*/
|
|
584
|
+
this.blockNumber = null;
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* A 66 character hexadecimal string representing the address the transaction is sent from.
|
|
588
|
+
* @type {string}
|
|
589
|
+
* @public
|
|
590
|
+
*/
|
|
591
|
+
this.from = null;
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* A 66 character hexadecimal string representing the hash of the transaction.
|
|
595
|
+
* @type {string}
|
|
596
|
+
* @public
|
|
597
|
+
*/
|
|
598
|
+
this.hash = null;
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* A 66 character hexadecimal string representing address the transaction is directed to.
|
|
602
|
+
* @type {string}
|
|
603
|
+
* @public
|
|
604
|
+
*/
|
|
605
|
+
this.to = null;
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* A hexadecimal string representing the value sent with this transaction. The value can be 0 for smart contract transactions, since it only represents the number of coins sent.
|
|
609
|
+
* @type {string}
|
|
610
|
+
* @public
|
|
611
|
+
*/
|
|
612
|
+
this.value = null;
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* A hexadecimal string representing either 0x1 (success) or 0x0 (failure). Failed transactions can also incur gas fee. You should consider the transaction as succeeded only if the status value is 0x1 (success).
|
|
616
|
+
* @type {string}
|
|
617
|
+
* @public
|
|
618
|
+
*/
|
|
619
|
+
this.status = null;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* @class
|
|
626
|
+
* @constructor
|
|
627
|
+
* @public
|
|
628
|
+
* @classdesc This class represents a list of account transactions returned by the listAccountTransactionDetails function.
|
|
629
|
+
*/
|
|
630
|
+
class ListAccountTransactionsResponse {
|
|
631
|
+
constructor() {
|
|
632
|
+
/**
|
|
633
|
+
* The number of pages available for listing.
|
|
634
|
+
* @type {number}
|
|
635
|
+
* @public
|
|
636
|
+
*/
|
|
637
|
+
this.pageCount = null;
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* An array of type AccountTransactionCompact, containing the list of transactions. Can be null if no items are available.
|
|
641
|
+
* @type {(AccountTransactionCompact|Array)}
|
|
642
|
+
* @public
|
|
643
|
+
*/
|
|
644
|
+
this.items = null;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* @class
|
|
651
|
+
* @constructor
|
|
652
|
+
* @public
|
|
653
|
+
* @classdesc This class represents a result from invoking the listAccountTransactionDetails function.
|
|
654
|
+
*/
|
|
655
|
+
class AccountTransactionsResult {
|
|
656
|
+
constructor(resultCode, listAccountTransactionsResponse, response, requestId, err) {
|
|
657
|
+
/**
|
|
658
|
+
* Represents the result of the operation. A value of 0 represents that the operation succeeded. Any other value indicates the operation failed. See the result code section for more details.
|
|
659
|
+
* @type {number}
|
|
660
|
+
* @public
|
|
661
|
+
*/
|
|
662
|
+
this.resultCode = resultCode;
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* An object of type ListAccountTransactionsResponse representing the list of transactions along with metadata. This value is null if the value of resultCode is not 0.
|
|
666
|
+
* @type {ListAccountTransactionsResponse}
|
|
667
|
+
* @public
|
|
668
|
+
*/
|
|
669
|
+
this.listAccountTransactionsResponse = listAccountTransactionsResponse;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* An object of representing the raw Response returned by the service. For details, see https://developer.mozilla.org/en-US/docs/Web/API/Response. This value can be null if the value of resultCode is not 0.
|
|
673
|
+
* @type {Object}
|
|
674
|
+
* @public
|
|
675
|
+
*/
|
|
676
|
+
this.response = response;
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* An unique id to represent the request. This can be null if request failed before it could be sent.
|
|
680
|
+
* @type {string}
|
|
681
|
+
* @public
|
|
682
|
+
*/
|
|
683
|
+
this.requestId = requestId;
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* An error object if the operation resulted in an error and there was no response. This property is defined only if the resultCode is -10000.
|
|
687
|
+
* @type {Error}
|
|
688
|
+
* @public
|
|
689
|
+
*/
|
|
690
|
+
this.err = err;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* @class
|
|
696
|
+
* @constructor
|
|
697
|
+
* @public
|
|
698
|
+
* @classdesc This class represents a signing request that can be passed to signTransaction.
|
|
699
|
+
*/
|
|
700
|
+
class TransactionSigningRequest {
|
|
701
|
+
/**
|
|
702
|
+
* Creates a TransactionSigningRequest class.
|
|
703
|
+
* @param {Wallet} wallet - The wallet with which the transaction has to be signed. The constructor does not verify the wallet. To verify a wallet, call the verifyWallet function explicitly.
|
|
704
|
+
* @param {string} toAddress - The address to which the transaction request is made. Can be null (for example, for contract creation).
|
|
705
|
+
* @param {string|BigInt} valueInWei - The value in wei-units. Can be provided as either a hex string (including 0x prefix) or a BigInt. For example, to represent 1 coin, which is 1000000000000000000 in wei-units, set the value to "0xDE0B6B3A7640000" or BigInt("1000000000000000000"). {@link /example/conversion-example.js|Conversion Examples}
|
|
706
|
+
* @param {number} nonce - A monotonically increasing number representing the nonce of the account signing the transaction. After each transaction from the account that gets registered in the blockchain, the nonce increases by 1.
|
|
707
|
+
* @param {string} data - An optional hex string (including 0x) that represents the contract data. Can be null if not invoking or creating a contract.
|
|
708
|
+
* @param {number} gasLimit - A limit of gas to be used. Set 21000 for basic non smart contract transactions.
|
|
709
|
+
* @param {string} remarks - An optional hex string (including 0x) that represents a remark (such as a comment). Maximum 32 bytes length (in bytes). Warning, do not store any sensitive information in this field.
|
|
710
|
+
* @param {number|null} chainId - The chain id of the blockchain. Mainnet chainId is 123123. Testnet T4 chainId is 310324. If null, the chainId specified in the initialize() function will be used.
|
|
711
|
+
* @param {number|null} signingContext - It is recommended that you pass null for this parameter, unless the context needs to be set explicitly. Signing context determines the cryptographic scheme used to sign. The wallet key type should compatible with the signing context. Applicable values are 0,1,2. Default value if not specified will be determined dynamically from the wallet key type. Signing context 1,2 will incur additional gas fee. For information on the schemes, see https://github.com/quantumcoinproject/circl?tab=readme-ov-file#hybrid-schemes
|
|
712
|
+
* Signing context 0: Scheme used is hybrid-ed-mldsa-slhdsa compact (scheme id 3)
|
|
713
|
+
* Signing context 1: Scheme used is hybrid-ed-mldsa-slhdsa-5 (scheme id 5 : 20x the gas fee of scheme 0)
|
|
714
|
+
* Signing context 2: hybrid-ed-mldsa-slhdsa full (scheme id 4 : 30x the gas fee of scheme 0)
|
|
715
|
+
*/
|
|
716
|
+
constructor(wallet, toAddress, valueInWei, nonce, data, gasLimit, remarks, chainId, signingContext) {
|
|
717
|
+
/**
|
|
718
|
+
* The wallet that should be used to sign the transaction.
|
|
719
|
+
* @type {Wallet}
|
|
720
|
+
* @public
|
|
721
|
+
*/
|
|
722
|
+
this.wallet = wallet;
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* The address to which the transaction request is made. Can be null (for example, for contract creation).
|
|
726
|
+
* @type {string|null}
|
|
727
|
+
* @public
|
|
728
|
+
*/
|
|
729
|
+
this.toAddress = toAddress;
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* The value in wei-units. Can be provided as either a hex string (including 0x prefix) or a BigInt. For example, to represent 1 coin, which is 1000000000000000000 in wei-units, set the value to "0xDE0B6B3A7640000" or BigInt("1000000000000000000"). {@link /example/conversion-example.js|Conversion Examples}
|
|
733
|
+
* @type {string|BigInt|null}
|
|
734
|
+
* @public
|
|
735
|
+
*/
|
|
736
|
+
this.valueInWei = valueInWei;
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* A monotonically increasing number representing the nonce of the account signing the transaction. After each transaction from the account that gets registered in the blockchain, the nonce increases by 1.
|
|
740
|
+
* @type {number}
|
|
741
|
+
* @public
|
|
742
|
+
*/
|
|
743
|
+
this.nonce = nonce;
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* An optional hex string (including 0x) that represents the contract data. Can be null if not invoking or creating a contract.
|
|
747
|
+
* @type {string|null}
|
|
748
|
+
* @public
|
|
749
|
+
*/
|
|
750
|
+
this.data = data;
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* A limit of gas to be used. Set 21000 for basic non smart contract transactions.
|
|
754
|
+
* @type {number}
|
|
755
|
+
* @public
|
|
756
|
+
*/
|
|
757
|
+
this.gasLimit = gasLimit;
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* An optional hex string (including 0x) that represents a remark (such as a comment). Maximum 32 bytes length (in bytes). Warning, do not store any sensitive information in this field.
|
|
761
|
+
* @type {string|null}
|
|
762
|
+
* @public
|
|
763
|
+
*/
|
|
764
|
+
this.remarks = remarks;
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* The chain id of the blockchain. Mainnet chainId is 123123. If null, the chainId specified in the initialize() function will be used.
|
|
768
|
+
* @type {number|null}
|
|
769
|
+
* @public
|
|
770
|
+
*/
|
|
771
|
+
this.chainId = chainId;
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* It is recommended that you pass null for this parameter, unless the context needs to be set explicitly. Signing context determines the cryptographic scheme used to sign. Gas fee varies by context.
|
|
775
|
+
* @type {number|null}
|
|
776
|
+
* @public
|
|
777
|
+
*/
|
|
778
|
+
this.signingContext = signingContext;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* @class
|
|
784
|
+
* @constructor
|
|
785
|
+
* @public
|
|
786
|
+
* @classdesc This class represents a result from invoking the packMethodData or unpackMethodData functions.
|
|
787
|
+
*/
|
|
788
|
+
class PackUnpackResult {
|
|
789
|
+
/**
|
|
790
|
+
* Creates a PackUnpackResult class.
|
|
791
|
+
* @param {string} error - Error message if any. Empty string if no error.
|
|
792
|
+
* @param {string} result - The actual result as a string. Empty string if there was an error.
|
|
793
|
+
*/
|
|
794
|
+
constructor(error, result) {
|
|
795
|
+
/**
|
|
796
|
+
* Error message if any. Empty string if no error.
|
|
797
|
+
* @type {string}
|
|
798
|
+
* @public
|
|
799
|
+
*/
|
|
800
|
+
this.error = error;
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* The actual result as a string. Empty string if there was an error.
|
|
804
|
+
* @type {string}
|
|
805
|
+
* @public
|
|
806
|
+
*/
|
|
807
|
+
this.result = result;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* @class EventLogEncodeResult
|
|
813
|
+
* @classdesc This class represents a result from invoking the encodeEventLog function.
|
|
814
|
+
*/
|
|
815
|
+
class EventLogEncodeResult {
|
|
816
|
+
/**
|
|
817
|
+
* Creates an EventLogEncodeResult class.
|
|
818
|
+
* @param {string} error - Error message if any. Empty string if no error.
|
|
819
|
+
* @param {Object|null} result - The actual result object with topics and data. Null if there was an error.
|
|
820
|
+
* @param {string[]} result.topics - Array of topic hex strings (with 0x prefix)
|
|
821
|
+
* @param {string} result.data - Hex-encoded data string (with 0x prefix)
|
|
822
|
+
*/
|
|
823
|
+
constructor(error, result) {
|
|
824
|
+
/**
|
|
825
|
+
* Error message if any. Empty string if no error.
|
|
826
|
+
* @type {string}
|
|
827
|
+
* @public
|
|
828
|
+
*/
|
|
829
|
+
this.error = error;
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* The actual result object with topics and data. Null if there was an error.
|
|
833
|
+
* @type {Object|null}
|
|
834
|
+
* @property {string[]} topics - Array of topic hex strings (with 0x prefix)
|
|
835
|
+
* @property {string} data - Hex-encoded data string (with 0x prefix)
|
|
836
|
+
* @public
|
|
837
|
+
*/
|
|
838
|
+
this.result = result;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
function isLargeNumber(val) {
|
|
843
|
+
if (val === null) {
|
|
844
|
+
return false;
|
|
845
|
+
}
|
|
846
|
+
if (typeof val === 'string' || val instanceof String) {
|
|
847
|
+
var rgx = /^([0-9]+([.][0-9]*)?|[.][0-9]+)$/;
|
|
848
|
+
return Boolean(val.match(rgx));
|
|
849
|
+
}
|
|
850
|
+
return false;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
function getGlobalObject() {
|
|
854
|
+
return (typeof globalThis !== 'undefined' ? globalThis : typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
async function InitAccountsWebAssembly() {
|
|
858
|
+
const go = new global.Go();
|
|
859
|
+
let mod, inst;
|
|
860
|
+
var base64wasm = wasmBase64.getBase64Wasm();
|
|
861
|
+
|
|
862
|
+
const base64bytes = atob(base64wasm);
|
|
863
|
+
if (base64bytes === null || base64bytes === undefined || base64bytes.length === 0) {
|
|
864
|
+
throw new Error("Error parsing base64");
|
|
865
|
+
}
|
|
866
|
+
const wasmBytes = Uint8Array.from(atob(base64wasm), c => c.charCodeAt(0));
|
|
867
|
+
|
|
868
|
+
const hashHex = crypto.createHash('sha256').update(wasmBytes).digest('hex');
|
|
869
|
+
if (hashHex !== EXPECTED_WASM_SHA256) {
|
|
870
|
+
throw new Error("WASM integrity check failed");
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
const g = getGlobalObject();
|
|
874
|
+
if (g) {
|
|
875
|
+
delete g.circl;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
let result = await WebAssembly.instantiate(wasmBytes, go.importObject);
|
|
879
|
+
mod = result.module;
|
|
880
|
+
inst = result.instance;
|
|
881
|
+
go.run(inst);
|
|
882
|
+
|
|
883
|
+
if (g && g.circl) {
|
|
884
|
+
circl = g.circl;
|
|
885
|
+
delete g.circl;
|
|
886
|
+
if (circl.hybridedmldsaslhdsa) Object.freeze(circl.hybridedmldsaslhdsa);
|
|
887
|
+
if (circl.hybridedmldsaslhdsa5) Object.freeze(circl.hybridedmldsaslhdsa5);
|
|
888
|
+
if (circl.hybridedmldsaslhds5) Object.freeze(circl.hybridedmldsaslhds5);
|
|
889
|
+
if (circl.hybrideds) Object.freeze(circl.hybrideds);
|
|
890
|
+
Object.freeze(circl);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
function validateCryptoRandom() {
|
|
895
|
+
if (!circl || !circl.cryptoRandom) {
|
|
896
|
+
return false;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
const sampleSize = 64;
|
|
900
|
+
const res1 = circl.cryptoRandom(sampleSize);
|
|
901
|
+
const res2 = circl.cryptoRandom(sampleSize);
|
|
902
|
+
|
|
903
|
+
if (!res1 || res1.error || !res1.result || res1.result.length !== sampleSize) {
|
|
904
|
+
return false;
|
|
905
|
+
}
|
|
906
|
+
if (!res2 || res2.error || !res2.result || res2.result.length !== sampleSize) {
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
const a = res1.result instanceof Uint8Array ? res1.result : new Uint8Array(res1.result);
|
|
911
|
+
const b = res2.result instanceof Uint8Array ? res2.result : new Uint8Array(res2.result);
|
|
912
|
+
|
|
913
|
+
let identical = true;
|
|
914
|
+
for (let i = 0; i < sampleSize; i++) {
|
|
915
|
+
if (a[i] !== b[i]) { identical = false; break; }
|
|
916
|
+
}
|
|
917
|
+
if (identical) {
|
|
918
|
+
return false;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
let aAllZero = true, bAllZero = true;
|
|
922
|
+
for (let i = 0; i < sampleSize; i++) {
|
|
923
|
+
if (a[i] !== 0) aAllZero = false;
|
|
924
|
+
if (b[i] !== 0) bAllZero = false;
|
|
925
|
+
}
|
|
926
|
+
if (aAllZero || bAllZero) {
|
|
927
|
+
return false;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const seen = new Set(a);
|
|
931
|
+
if (seen.size < 48) {
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
return true;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* The initialize function has to be called before attempting to invoke any other function. This function should be called only once.
|
|
940
|
+
*
|
|
941
|
+
* @async
|
|
942
|
+
* @function initialize
|
|
943
|
+
* @param {Config|undefined} clientConfig - A configuration represented by the Config class. A default configuration is used, if not specified.
|
|
944
|
+
* @return {Promise<boolean>} Returns a promise of type boolean; true if the initialization succeeded, else false.
|
|
945
|
+
*/
|
|
946
|
+
async function initialize(clientConfig) {
|
|
947
|
+
if (isInitialized === true) {
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
if (clientConfig === null || clientConfig === undefined) {
|
|
951
|
+
clientConfig = new Config("https://sdk.readrelay.quantumcoinapi.com", "https://sdk.writerelay.quantumcoinapi.com", 123123, "", ""); //default
|
|
952
|
+
}
|
|
953
|
+
if (clientConfig.readUrl === null || clientConfig.writeUrl === null || clientConfig.chainId === null) {
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
await InitAccountsWebAssembly();
|
|
957
|
+
if (!validateCryptoRandom()) {
|
|
958
|
+
throw new Error("CSPRNG validation failed");
|
|
959
|
+
}
|
|
960
|
+
config = clientConfig;
|
|
961
|
+
isInitialized = await seedwords.initialize();
|
|
962
|
+
|
|
963
|
+
return isInitialized;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* The isAddressValid function validates whether an address is valid or not. An address is of length 66 characters including 0x.
|
|
968
|
+
*
|
|
969
|
+
* @function isAddressValid
|
|
970
|
+
* @param {string} address - A string representing the address to validate.
|
|
971
|
+
* @return {boolean} Returns true if the address validation succeeded, else returns false.
|
|
972
|
+
*/
|
|
973
|
+
function isAddressValid(address) {
|
|
974
|
+
if (isInitialized === false) {
|
|
975
|
+
return -1000;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
if (address === null) {
|
|
979
|
+
return false;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
if (address.length !== 66) {
|
|
983
|
+
return false;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
if (typeof address === 'string' || address instanceof String) {
|
|
987
|
+
return IsValidAddress(address);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
return false;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
* Internal: get key type (KEY_TYPE_HYBRIDEDMLDSASLHDSA or KEY_TYPE_HYBRIDEDMLDSASLHDSA5) from private key length.
|
|
995
|
+
* @param {number[]|Uint8Array} privateKey - Wallet private key bytes.
|
|
996
|
+
* @returns {number|null} KEY_TYPE_HYBRIDEDMLDSASLHDSA (3), KEY_TYPE_HYBRIDEDMLDSASLHDSA5 (5), or null on error.
|
|
997
|
+
*/
|
|
998
|
+
function getKeyTypeFromPrivateKey(privateKey) {
|
|
999
|
+
if (circl == null || !privateKey || typeof privateKey.length !== 'number') {
|
|
1000
|
+
return null;
|
|
1001
|
+
}
|
|
1002
|
+
const len = privateKey.length;
|
|
1003
|
+
const hybridNs = circl.hybridedmldsaslhdsa;
|
|
1004
|
+
const hybrid5Ns = circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5;
|
|
1005
|
+
if (hybridNs && len === hybridNs.PrivateKeySize) {
|
|
1006
|
+
return KEY_TYPE_HYBRIDEDMLDSASLHDSA;
|
|
1007
|
+
}
|
|
1008
|
+
if (hybrid5Ns && len === hybrid5Ns.PrivateKeySize) {
|
|
1009
|
+
return KEY_TYPE_HYBRIDEDMLDSASLHDSA5;
|
|
1010
|
+
}
|
|
1011
|
+
return null;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Internal: get key type (KEY_TYPE_HYBRIDEDMLDSASLHDSA or KEY_TYPE_HYBRIDEDMLDSASLHDSA5) from public key length.
|
|
1016
|
+
* @param {number[]|Uint8Array} publicKey - Public key bytes.
|
|
1017
|
+
* @returns {number|null} KEY_TYPE_HYBRIDEDMLDSASLHDSA (3), KEY_TYPE_HYBRIDEDMLDSASLHDSA5 (5), or null on error.
|
|
1018
|
+
*/
|
|
1019
|
+
function getKeyTypeFromPublicKey(publicKey) {
|
|
1020
|
+
if (circl == null || !publicKey || typeof publicKey.length !== 'number') {
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
1023
|
+
const len = publicKey.byteLength !== undefined ? publicKey.byteLength : publicKey.length;
|
|
1024
|
+
const hybridNs = circl.hybridedmldsaslhdsa;
|
|
1025
|
+
const hybrid5Ns = circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5;
|
|
1026
|
+
if (hybridNs && typeof hybridNs.PublicKeySize === 'number' && len === hybridNs.PublicKeySize) {
|
|
1027
|
+
return KEY_TYPE_HYBRIDEDMLDSASLHDSA;
|
|
1028
|
+
}
|
|
1029
|
+
if (hybrid5Ns && typeof hybrid5Ns.PublicKeySize === 'number' && len === hybrid5Ns.PublicKeySize) {
|
|
1030
|
+
return KEY_TYPE_HYBRIDEDMLDSASLHDSA5;
|
|
1031
|
+
}
|
|
1032
|
+
return null;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* Convert key (number[] or Uint8Array) to Uint8Array for CIRCL.
|
|
1037
|
+
* @param {number[]|Uint8Array} key - Key bytes.
|
|
1038
|
+
* @returns {Uint8Array}
|
|
1039
|
+
*/
|
|
1040
|
+
function toUint8Array(key) {
|
|
1041
|
+
if (key instanceof Uint8Array) return key;
|
|
1042
|
+
return new Uint8Array(key);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/**
|
|
1046
|
+
* The newWallet function creates a new Wallet.
|
|
1047
|
+
* @function newWallet
|
|
1048
|
+
* @param {number|null} keyType - Optional. KEY_TYPE_HYBRIDEDMLDSASLHDSA (3) or KEY_TYPE_HYBRIDEDMLDSASLHDSA5 (5). null/undefined defaults to 3.
|
|
1049
|
+
* @return {Wallet|number} Returns a Wallet object, or -1000 (not initialized), -1001 (invalid key type), -1002 (crypto failure).
|
|
1050
|
+
*/
|
|
1051
|
+
function newWallet(keyType) {
|
|
1052
|
+
if (isInitialized === false) {
|
|
1053
|
+
return -1000;
|
|
1054
|
+
}
|
|
1055
|
+
if (circl == null) {
|
|
1056
|
+
return CIRCL_CRYPTO_FAILURE;
|
|
1057
|
+
}
|
|
1058
|
+
if (keyType === null || keyType === undefined) {
|
|
1059
|
+
keyType = KEY_TYPE_HYBRIDEDMLDSASLHDSA;
|
|
1060
|
+
}
|
|
1061
|
+
const hybridNs = circl.hybridedmldsaslhdsa;
|
|
1062
|
+
const hybrid5Ns = circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5;
|
|
1063
|
+
let res;
|
|
1064
|
+
if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA && hybridNs) {
|
|
1065
|
+
res = hybridNs.generateKey();
|
|
1066
|
+
} else if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5 && hybrid5Ns) {
|
|
1067
|
+
res = hybrid5Ns.generateKey();
|
|
1068
|
+
} else {
|
|
1069
|
+
return INVALID_KEY_TYPE;
|
|
1070
|
+
}
|
|
1071
|
+
if (res && res.error) {
|
|
1072
|
+
return CIRCL_CRYPTO_FAILURE;
|
|
1073
|
+
}
|
|
1074
|
+
if (!res || !res.result || !res.result.publicKey || !res.result.privateKey) {
|
|
1075
|
+
return CIRCL_CRYPTO_FAILURE;
|
|
1076
|
+
}
|
|
1077
|
+
const publicKey = res.result.publicKey instanceof Uint8Array ? Array.from(res.result.publicKey) : res.result.publicKey;
|
|
1078
|
+
const privateKey = res.result.privateKey instanceof Uint8Array ? Array.from(res.result.privateKey) : res.result.privateKey;
|
|
1079
|
+
const address = PublicKeyToAddress(publicKey);
|
|
1080
|
+
return new Wallet(address, privateKey, publicKey);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* The newWalletSeedWords function creates a new wallet seed word list. The returned array can then be passed to the openWalletFromSeedWords function to create a new wallet.
|
|
1085
|
+
*
|
|
1086
|
+
* @function newWalletSeedWords
|
|
1087
|
+
* @param {number|null} keyType - Optional. KEY_TYPE_HYBRIDEDMLDSASLHDSA (3) or KEY_TYPE_HYBRIDEDMLDSASLHDSA5 (5). null/undefined defaults to 3.
|
|
1088
|
+
* @return {string[]|number|null} Returns an array of seed words (32 or 36 words depending on keyType). Returns -1000 if not initialized, null on failure.
|
|
1089
|
+
*/
|
|
1090
|
+
function newWalletSeedWords(keyType) {
|
|
1091
|
+
if (isInitialized === false) {
|
|
1092
|
+
return -1000;
|
|
1093
|
+
}
|
|
1094
|
+
if (circl == null || !circl.cryptoRandom) {
|
|
1095
|
+
return null;
|
|
1096
|
+
}
|
|
1097
|
+
if (keyType === null || keyType === undefined) {
|
|
1098
|
+
keyType = KEY_TYPE_HYBRIDEDMLDSASLHDSA;
|
|
1099
|
+
}
|
|
1100
|
+
if (keyType !== KEY_TYPE_HYBRIDEDMLDSASLHDSA && keyType !== KEY_TYPE_HYBRIDEDMLDSASLHDSA5) {
|
|
1101
|
+
return null;
|
|
1102
|
+
}
|
|
1103
|
+
const baseSeedLen = keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5 ? BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA5 : BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA;
|
|
1104
|
+
const res = circl.cryptoRandom(baseSeedLen);
|
|
1105
|
+
if (res && res.error) {
|
|
1106
|
+
return null;
|
|
1107
|
+
}
|
|
1108
|
+
if (!res || !res.result || res.result.length !== baseSeedLen) {
|
|
1109
|
+
return null;
|
|
1110
|
+
}
|
|
1111
|
+
const seedArray = res.result instanceof Uint8Array ? res.result : new Uint8Array(res.result);
|
|
1112
|
+
const wordList = seedwords.getWordListFromSeedArray(seedArray);
|
|
1113
|
+
const expectedLen = keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5 ? SEED_WORD_LIST_LENGTH_HYBRIDEDMLDSASLHDSA5 : SEED_WORD_LIST_LENGTH_HYBRIDEDMLDSASLHDSA;
|
|
1114
|
+
if (wordList == null || wordList.length !== expectedLen) {
|
|
1115
|
+
return null;
|
|
1116
|
+
}
|
|
1117
|
+
return wordList;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
/**
|
|
1121
|
+
* The openWalletFromSeed function creates a wallet from a raw seed byte array.
|
|
1122
|
+
* Determines the key scheme from the array length: 96 bytes (hybrideds), 72 bytes (hybrid5), or 64 bytes (hybrid).
|
|
1123
|
+
*
|
|
1124
|
+
* @function openWalletFromSeed
|
|
1125
|
+
* @param {Array<number>|Uint8Array} seedArray - The raw seed bytes. Length 96, 72, or 64 depending on scheme.
|
|
1126
|
+
* @return {Wallet|number|null} Returns a Wallet object. Returns -1000 if not initialized, null if the operation failed.
|
|
1127
|
+
*/
|
|
1128
|
+
function openWalletFromSeed(seedArray) {
|
|
1129
|
+
if (isInitialized === false) {
|
|
1130
|
+
return -1000;
|
|
1131
|
+
}
|
|
1132
|
+
if (seedArray == null || typeof seedArray.length !== 'number') {
|
|
1133
|
+
return null;
|
|
1134
|
+
}
|
|
1135
|
+
const len = seedArray.length;
|
|
1136
|
+
if (len !== BASE_SEED_BYTES_HYBRIDEDS && len !== BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA5 && len !== BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA) {
|
|
1137
|
+
return null;
|
|
1138
|
+
}
|
|
1139
|
+
if (circl == null) {
|
|
1140
|
+
return null;
|
|
1141
|
+
}
|
|
1142
|
+
let expandedRes;
|
|
1143
|
+
let keyPairRes;
|
|
1144
|
+
const seedU8 = seedArray instanceof Uint8Array ? seedArray : new Uint8Array(seedArray);
|
|
1145
|
+
if (len === BASE_SEED_BYTES_HYBRIDEDS) {
|
|
1146
|
+
const ns = circl.hybrideds;
|
|
1147
|
+
if (!ns) return null;
|
|
1148
|
+
expandedRes = ns.expandSeed(seedU8);
|
|
1149
|
+
if (expandedRes && expandedRes.error) return null;
|
|
1150
|
+
if (!expandedRes || !expandedRes.result) return null;
|
|
1151
|
+
keyPairRes = ns.newKeyFromSeed(expandedRes.result);
|
|
1152
|
+
} else if (len === BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA5) {
|
|
1153
|
+
const ns = circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5;
|
|
1154
|
+
if (!ns) return null;
|
|
1155
|
+
expandedRes = ns.expandSeed(seedU8);
|
|
1156
|
+
if (expandedRes && expandedRes.error) return null;
|
|
1157
|
+
if (!expandedRes || !expandedRes.result) return null;
|
|
1158
|
+
keyPairRes = ns.newKeyFromSeed(expandedRes.result);
|
|
1159
|
+
} else {
|
|
1160
|
+
const ns = circl.hybridedmldsaslhdsa;
|
|
1161
|
+
if (!ns) return null;
|
|
1162
|
+
expandedRes = ns.expandSeed(seedU8);
|
|
1163
|
+
if (expandedRes && expandedRes.error) return null;
|
|
1164
|
+
if (!expandedRes || !expandedRes.result) return null;
|
|
1165
|
+
keyPairRes = ns.newKeyFromSeed(expandedRes.result);
|
|
1166
|
+
}
|
|
1167
|
+
if (keyPairRes && keyPairRes.error) return null;
|
|
1168
|
+
if (!keyPairRes || !keyPairRes.result || !keyPairRes.result.publicKey || !keyPairRes.result.privateKey) return null;
|
|
1169
|
+
const publicKey = keyPairRes.result.publicKey instanceof Uint8Array ? Array.from(keyPairRes.result.publicKey) : keyPairRes.result.publicKey;
|
|
1170
|
+
const privateKey = keyPairRes.result.privateKey instanceof Uint8Array ? Array.from(keyPairRes.result.privateKey) : keyPairRes.result.privateKey;
|
|
1171
|
+
const address = PublicKeyToAddress(publicKey);
|
|
1172
|
+
return new Wallet(address, privateKey, publicKey, seedU8);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/**
|
|
1176
|
+
* The openWalletFromSeedWords function creates a wallet from a seed word list. The seed word list is available for wallets created from Desktop/Web/Mobile wallets.
|
|
1177
|
+
* Supports 48 words (hybrideds), 36 words (hybrid5), or 32 words (hybrid) per seed length.
|
|
1178
|
+
*
|
|
1179
|
+
* @function openWalletFromSeedWords
|
|
1180
|
+
* @param {string[]} seedWordList - An array of seed words. Length 48, 36, or 32 depending on scheme.
|
|
1181
|
+
* @return {Wallet|number|null} Returns a Wallet object. Returns -1000 if not initialized, null if the operation failed.
|
|
1182
|
+
*/
|
|
1183
|
+
function openWalletFromSeedWords(seedWordList) {
|
|
1184
|
+
if (isInitialized === false) {
|
|
1185
|
+
return -1000;
|
|
1186
|
+
}
|
|
1187
|
+
if (seedWordList == null || typeof seedWordList.length !== 'number') {
|
|
1188
|
+
return null;
|
|
1189
|
+
}
|
|
1190
|
+
const len = seedWordList.length;
|
|
1191
|
+
if (len !== SEED_WORD_LIST_LENGTH_HYBRIDEDS && len !== SEED_WORD_LIST_LENGTH_HYBRIDEDMLDSASLHDSA5 && len !== SEED_WORD_LIST_LENGTH_HYBRIDEDMLDSASLHDSA) {
|
|
1192
|
+
return null;
|
|
1193
|
+
}
|
|
1194
|
+
const seedArray = seedwords.getSeedArrayFromWordList(seedWordList);
|
|
1195
|
+
if (seedArray == null || seedArray.length === undefined) {
|
|
1196
|
+
return null;
|
|
1197
|
+
}
|
|
1198
|
+
return openWalletFromSeed(seedArray);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* The deserializeEncryptedWallet function opens a wallet backed-up using an application such as the Desktop/Mobile/CLI/Web wallet. This function can take upto a minute or so to execute. You should open wallets only from trusted sources.
|
|
1203
|
+
*
|
|
1204
|
+
* @function deserializeEncryptedWallet
|
|
1205
|
+
* @param {string} walletJsonString - The json string from a wallet file.
|
|
1206
|
+
* @param {string} passphrase - The passphrase used to encrypt the wallet.
|
|
1207
|
+
* @return {Wallet} Returns a Wallet object. Returns null if opening the wallet fails.
|
|
1208
|
+
*/
|
|
1209
|
+
function deserializeEncryptedWallet(walletJsonString, passphrase) {
|
|
1210
|
+
if (isInitialized === false) {
|
|
1211
|
+
return -1000;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
if (walletJsonString == null || passphrase == null) {
|
|
1215
|
+
return null;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
if (typeof walletJsonString === 'string' || walletJsonString instanceof String) {
|
|
1219
|
+
|
|
1220
|
+
} else {
|
|
1221
|
+
return null;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
if (typeof passphrase === 'string' || passphrase instanceof String) {
|
|
1225
|
+
|
|
1226
|
+
} else {
|
|
1227
|
+
return null;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
let walletJsonObj;
|
|
1231
|
+
try {
|
|
1232
|
+
walletJsonObj = JSON.parse(walletJsonString);
|
|
1233
|
+
} catch (e) {
|
|
1234
|
+
return null;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
if (walletJsonObj == null) {
|
|
1238
|
+
return null;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
if (walletJsonObj.address == null) {
|
|
1242
|
+
return null;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
let keyPairString = JsonToWalletKeyPair(walletJsonString, passphrase);
|
|
1246
|
+
if (keyPairString == null) {
|
|
1247
|
+
return null;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
let keyPairSplit = keyPairString.split(",");
|
|
1251
|
+
if (keyPairSplit.length < 2) {
|
|
1252
|
+
return null;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
let privateKeyArray = base64ToBytes(keyPairSplit[0]);
|
|
1256
|
+
let publicKeyArray = base64ToBytes(keyPairSplit[1]);
|
|
1257
|
+
let preExpansionSeed = null;
|
|
1258
|
+
if (keyPairSplit.length >= 3 && keyPairSplit[2].length > 0) {
|
|
1259
|
+
preExpansionSeed = base64ToBytes(keyPairSplit[2]);
|
|
1260
|
+
}
|
|
1261
|
+
let address = PublicKeyToAddress(publicKeyArray);
|
|
1262
|
+
if (address == null) {
|
|
1263
|
+
return null;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
if (typeof address === 'string' || address instanceof String) {
|
|
1267
|
+
|
|
1268
|
+
} else {
|
|
1269
|
+
return null;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
let addressCheck = "0x" + walletJsonObj.address.toLowerCase();
|
|
1273
|
+
if (addressCheck !== address.toLowerCase()) {
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
let wallet = new Wallet(address, privateKeyArray, publicKeyArray, preExpansionSeed);
|
|
1278
|
+
|
|
1279
|
+
return wallet;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* The serializeEncryptedWallet function encrypts and serializes a Wallet object to a JSON string readable by the Desktop/Mobile/Web/CLI wallet applications. You can save this string to a file and open the file in one of these wallet applications. You may also open this string using the deserializeEncryptedWallet function. If you loose the passphrase, you will be unable to open the wallet. This function can take upto a minute or so to execute.
|
|
1284
|
+
*
|
|
1285
|
+
* @function serializeEncryptedWallet
|
|
1286
|
+
* @param {Wallet} wallet - A Wallet object representing the wallet to serialize.
|
|
1287
|
+
* @param {string} passphrase - A passphrase used to encrypt the wallet. It should atleast be 12 characters long.
|
|
1288
|
+
* @return {string} Returns the Wallet in JSON string format. If the wallet is invalid, null is returned.
|
|
1289
|
+
*/
|
|
1290
|
+
function serializeEncryptedWallet(wallet, passphrase) {
|
|
1291
|
+
if(verifyWallet(wallet) === false) {
|
|
1292
|
+
return null;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
if (passphrase == null) {
|
|
1296
|
+
return null;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
if (typeof passphrase === 'string' || passphrase instanceof String) {
|
|
1300
|
+
|
|
1301
|
+
} else {
|
|
1302
|
+
return null;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
if (passphrase.length < MIN_PASSPHRASE_LENGTH) {
|
|
1306
|
+
return null;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
let walletJsonString;
|
|
1310
|
+
if (wallet.preExpansionSeed != null && wallet.preExpansionSeed.length > 0) {
|
|
1311
|
+
const seedU8 = wallet.preExpansionSeed instanceof Uint8Array ? wallet.preExpansionSeed : new Uint8Array(wallet.preExpansionSeed);
|
|
1312
|
+
const result = EncryptPreExpansionSeed(seedU8, passphrase);
|
|
1313
|
+
if (result == null || result instanceof Error) {
|
|
1314
|
+
return null;
|
|
1315
|
+
}
|
|
1316
|
+
walletJsonString = result;
|
|
1317
|
+
} else {
|
|
1318
|
+
walletJsonString = KeyPairToWalletJson(wallet.privateKey, wallet.publicKey, passphrase);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
let walletJson = JSON.parse(walletJsonString);
|
|
1322
|
+
let addressCheck = "0x" + walletJson.address;
|
|
1323
|
+
if (addressCheck.toLowerCase() !== wallet.address.toLowerCase()) {
|
|
1324
|
+
return null;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
return walletJsonString;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
/**
|
|
1331
|
+
* The serializeSeedAsEncryptedWallet function encrypts a raw seed byte array into a wallet JSON string
|
|
1332
|
+
* that can be opened with deserializeEncryptedWallet or Desktop/Mobile/Web/CLI wallet applications.
|
|
1333
|
+
* The seed is stored in its pre-expansion form (version 5 wallet format). This function can take
|
|
1334
|
+
* up to a minute or so to execute due to key derivation.
|
|
1335
|
+
*
|
|
1336
|
+
* @function serializeSeedAsEncryptedWallet
|
|
1337
|
+
* @param {Array<number>|Uint8Array} seedArray - The raw seed bytes. Length must be 96, 72, or 64 depending on scheme.
|
|
1338
|
+
* @param {string} passphrase - A passphrase used to encrypt the wallet. Must be at least 12 characters long.
|
|
1339
|
+
* @return {string|number|null} Returns the encrypted wallet JSON string. Returns -1000 if not initialized, null if the operation failed.
|
|
1340
|
+
*/
|
|
1341
|
+
function serializeSeedAsEncryptedWallet(seedArray, passphrase) {
|
|
1342
|
+
if (isInitialized === false) {
|
|
1343
|
+
return -1000;
|
|
1344
|
+
}
|
|
1345
|
+
if (seedArray == null || typeof seedArray.length !== 'number') {
|
|
1346
|
+
return null;
|
|
1347
|
+
}
|
|
1348
|
+
const len = seedArray.length;
|
|
1349
|
+
if (len !== BASE_SEED_BYTES_HYBRIDEDS && len !== BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA5 && len !== BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA) {
|
|
1350
|
+
return null;
|
|
1351
|
+
}
|
|
1352
|
+
if (passphrase == null) {
|
|
1353
|
+
return null;
|
|
1354
|
+
}
|
|
1355
|
+
if (typeof passphrase !== 'string' && !(passphrase instanceof String)) {
|
|
1356
|
+
return null;
|
|
1357
|
+
}
|
|
1358
|
+
if (passphrase.length < MIN_PASSPHRASE_LENGTH) {
|
|
1359
|
+
return null;
|
|
1360
|
+
}
|
|
1361
|
+
const seedU8 = seedArray instanceof Uint8Array ? seedArray : new Uint8Array(seedArray);
|
|
1362
|
+
const result = EncryptPreExpansionSeed(seedU8, passphrase);
|
|
1363
|
+
if (result == null || result instanceof Error) {
|
|
1364
|
+
return null;
|
|
1365
|
+
}
|
|
1366
|
+
return result;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
function base64ToBytes(base64) {
|
|
1370
|
+
const binString = atob(base64);
|
|
1371
|
+
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
function bytesToBase64(bytes) {
|
|
1375
|
+
const binString = Array.from(bytes, (byte) =>
|
|
1376
|
+
String.fromCodePoint(byte),
|
|
1377
|
+
).join("");
|
|
1378
|
+
return btoa(binString);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
function getRandomRequestId() {
|
|
1382
|
+
return crypto.randomBytes(20).toString('hex');
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
function isByteArray(array) {
|
|
1386
|
+
if (!array) return false;
|
|
1387
|
+
if (array.byteLength !== undefined) return true;
|
|
1388
|
+
if (typeof array.length === 'number' && array.length >= 0) return true;
|
|
1389
|
+
return false;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
/**
|
|
1393
|
+
* The verifyWallet function verifies whether a Wallet is valid or not. To mitigate spoofing and other attachs, it is highly recommended to verify a wallet, especially if it is from an untrusted source.
|
|
1394
|
+
*
|
|
1395
|
+
* @function verifyWallet
|
|
1396
|
+
* @param {Wallet} wallet - A Wallet object representing the wallet to verify.
|
|
1397
|
+
* @return {boolean} Returns true if the Wallet verification succeeded, else returns false.
|
|
1398
|
+
*/
|
|
1399
|
+
function verifyWallet(wallet) {
|
|
1400
|
+
if (isInitialized === false) {
|
|
1401
|
+
return -1000;
|
|
1402
|
+
}
|
|
1403
|
+
if (wallet === null || wallet.address === null || wallet.privateKey === null || wallet.publicKey === null) {
|
|
1404
|
+
return false;
|
|
1405
|
+
}
|
|
1406
|
+
if (isAddressValid(wallet.address) === false) {
|
|
1407
|
+
return false;
|
|
1408
|
+
}
|
|
1409
|
+
if (isByteArray(wallet.privateKey) === false) {
|
|
1410
|
+
return false;
|
|
1411
|
+
}
|
|
1412
|
+
if (isByteArray(wallet.publicKey) === false) {
|
|
1413
|
+
return false;
|
|
1414
|
+
}
|
|
1415
|
+
const keyType = getKeyTypeFromPrivateKey(wallet.privateKey);
|
|
1416
|
+
if (keyType == null) {
|
|
1417
|
+
return false;
|
|
1418
|
+
}
|
|
1419
|
+
const hybridNs = circl && circl.hybridedmldsaslhdsa;
|
|
1420
|
+
const hybrid5Ns = circl && (circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5);
|
|
1421
|
+
if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA && hybridNs && wallet.privateKey.length !== hybridNs.PrivateKeySize) {
|
|
1422
|
+
return false;
|
|
1423
|
+
}
|
|
1424
|
+
if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5 && hybrid5Ns && wallet.privateKey.length !== hybrid5Ns.PrivateKeySize) {
|
|
1425
|
+
return false;
|
|
1426
|
+
}
|
|
1427
|
+
const address = PublicKeyToAddress(wallet.publicKey);
|
|
1428
|
+
if (address !== wallet.address) {
|
|
1429
|
+
return false;
|
|
1430
|
+
}
|
|
1431
|
+
const message = new TextEncoder().encode("verifyverifyverifyverifyverifyok");
|
|
1432
|
+
const privU8 = toUint8Array(wallet.privateKey);
|
|
1433
|
+
const pubU8 = toUint8Array(wallet.publicKey);
|
|
1434
|
+
let sigRes;
|
|
1435
|
+
let verRes;
|
|
1436
|
+
if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA && hybridNs) {
|
|
1437
|
+
sigRes = hybridNs.sign(privU8, message);
|
|
1438
|
+
if (sigRes && sigRes.error) {
|
|
1439
|
+
return false;
|
|
1440
|
+
}
|
|
1441
|
+
verRes = hybridNs.verify(pubU8, message, sigRes.result);
|
|
1442
|
+
} else if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5 && hybrid5Ns) {
|
|
1443
|
+
sigRes = hybrid5Ns.sign(privU8, message);
|
|
1444
|
+
if (sigRes && sigRes.error) {
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
verRes = hybrid5Ns.verify(pubU8, message, sigRes.result);
|
|
1448
|
+
} else {
|
|
1449
|
+
return false;
|
|
1450
|
+
}
|
|
1451
|
+
if (verRes && verRes.error) {
|
|
1452
|
+
return false;
|
|
1453
|
+
}
|
|
1454
|
+
if (!(verRes && verRes.result === true)) {
|
|
1455
|
+
return false;
|
|
1456
|
+
}
|
|
1457
|
+
return true;
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
/**
|
|
1461
|
+
* The serializeWallet function serializes a Wallet object to a JSON string. You should encrypt the string before saving it to disk or a database.
|
|
1462
|
+
*
|
|
1463
|
+
* @function serializeWallet
|
|
1464
|
+
* @param {Wallet} wallet - A Wallet object representing the wallet to serialize.
|
|
1465
|
+
* @return {string} Returns the Wallet in JSON string format. If the wallet is invalid, null is returned.
|
|
1466
|
+
*/
|
|
1467
|
+
function serializeWallet(wallet) {
|
|
1468
|
+
if (isInitialized === false) {
|
|
1469
|
+
return -1000;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
if(verifyWallet(wallet) === false) {
|
|
1473
|
+
return null;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
var walletJson = {
|
|
1477
|
+
"address": wallet.address,
|
|
1478
|
+
"privateKey": bytesToBase64(wallet.privateKey),
|
|
1479
|
+
"publicKey": bytesToBase64(wallet.publicKey),
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
if (wallet.preExpansionSeed != null && wallet.preExpansionSeed.length > 0) {
|
|
1483
|
+
walletJson.preExpansionSeed = bytesToBase64(wallet.preExpansionSeed);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
return JSON.stringify(walletJson);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
/**
|
|
1490
|
+
* The deserializeWallet function creates a Wallet object from a JSON string.
|
|
1491
|
+
*
|
|
1492
|
+
* @function deserializeWallet
|
|
1493
|
+
* @param {string} walletJson - A JSON string representing the wallet to deserialize.
|
|
1494
|
+
* @return {Wallet|null} Returns the Wallet corresponding to the walletJson. If the wallet is invalid or the JSON is malformed, null is returned.
|
|
1495
|
+
*/
|
|
1496
|
+
function deserializeWallet(walletJson) {
|
|
1497
|
+
if (isInitialized === false) {
|
|
1498
|
+
return -1000;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
try {
|
|
1502
|
+
var tempWallet = JSON.parse(walletJson);
|
|
1503
|
+
if (tempWallet == null || typeof tempWallet !== 'object') {
|
|
1504
|
+
return null;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
var preExpansionSeed = null;
|
|
1508
|
+
if (tempWallet.preExpansionSeed != null && tempWallet.preExpansionSeed.length > 0) {
|
|
1509
|
+
preExpansionSeed = base64ToBytes(tempWallet.preExpansionSeed);
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
var wallet = new Wallet(tempWallet.address, base64ToBytes(tempWallet.privateKey), base64ToBytes(tempWallet.publicKey), preExpansionSeed);
|
|
1513
|
+
|
|
1514
|
+
if (verifyWallet(wallet) === false) {
|
|
1515
|
+
return null;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
return wallet;
|
|
1519
|
+
} catch (e) {
|
|
1520
|
+
return null;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
function transactionGetSigningHash(fromaddress, nonce, toaddress, amount, gas, chainid, data) {
|
|
1525
|
+
let messageData = TxnSigningHash(fromaddress, nonce, toaddress, amount, gas, chainid, data);
|
|
1526
|
+
var messageBytes = [];
|
|
1527
|
+
for (var i = 0; i < messageData.length; ++i) {
|
|
1528
|
+
messageBytes.push(messageData.charCodeAt(i));
|
|
1529
|
+
}
|
|
1530
|
+
return messageBytes;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
function transactionGetTransactionHash(fromaddress, nonce, toaddress, amount, gas, chainid, data, pkkey, sig) {
|
|
1534
|
+
const arrayPkDataToPass = pkkey.toString().split(",");
|
|
1535
|
+
const typedPkArray = new Uint8Array(arrayPkDataToPass.length);
|
|
1536
|
+
for (let i = 0; i < arrayPkDataToPass.length; i++) {
|
|
1537
|
+
typedPkArray[i] = arrayPkDataToPass[i];
|
|
1538
|
+
}
|
|
1539
|
+
const arraySigDataToPass = sig.toString().split(",");
|
|
1540
|
+
const typedSigArray = new Uint8Array(arraySigDataToPass.length);
|
|
1541
|
+
for (let i = 0; i < arraySigDataToPass.length; i++) {
|
|
1542
|
+
typedSigArray[i] = arraySigDataToPass[i];
|
|
1543
|
+
}
|
|
1544
|
+
var txnHash = TxnHash(fromaddress, nonce, toaddress, amount, gas, chainid, data, typedPkArray, typedSigArray)
|
|
1545
|
+
return txnHash;
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
function transactionGetData(fromaddress, nonce, toaddress, amount, gas, chainid, data, pkkey, sig) {
|
|
1549
|
+
const arrayPkDataToPass = pkkey.toString().split(",");
|
|
1550
|
+
const typedPkArray = new Uint8Array(arrayPkDataToPass.length);
|
|
1551
|
+
for (let i = 0; i < arrayPkDataToPass.length; i++) {
|
|
1552
|
+
typedPkArray[i] = arrayPkDataToPass[i];
|
|
1553
|
+
}
|
|
1554
|
+
const arraySigDataToPass = sig.toString().split(",");
|
|
1555
|
+
const typedSigArray = new Uint8Array(arraySigDataToPass.length);
|
|
1556
|
+
for (let i = 0; i < arraySigDataToPass.length; i++) {
|
|
1557
|
+
typedSigArray[i] = arraySigDataToPass[i];
|
|
1558
|
+
}
|
|
1559
|
+
var txnData = TxnData(fromaddress, nonce, toaddress, amount, gas, chainid, data, typedPkArray, typedSigArray)
|
|
1560
|
+
return txnData;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
function transactionGetSigningHash2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext) {
|
|
1564
|
+
let messageDataReturn = TxnSigningHash2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext);
|
|
1565
|
+
if (messageDataReturn && messageDataReturn.error) {
|
|
1566
|
+
return null;
|
|
1567
|
+
}
|
|
1568
|
+
var messageData = messageDataReturn.result;
|
|
1569
|
+
var messageBytes = [];
|
|
1570
|
+
for (var i = 0; i < messageData.length; ++i) {
|
|
1571
|
+
messageBytes.push(messageData.charCodeAt(i));
|
|
1572
|
+
}
|
|
1573
|
+
return messageBytes;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
function transactionGetTransactionHash2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext, pkkey, sig) {
|
|
1577
|
+
const arrayPkDataToPass = pkkey.toString().split(",");
|
|
1578
|
+
const typedPkArray = new Uint8Array(arrayPkDataToPass.length);
|
|
1579
|
+
for (let i = 0; i < arrayPkDataToPass.length; i++) {
|
|
1580
|
+
typedPkArray[i] = arrayPkDataToPass[i];
|
|
1581
|
+
}
|
|
1582
|
+
const arraySigDataToPass = sig.toString().split(",");
|
|
1583
|
+
const typedSigArray = new Uint8Array(arraySigDataToPass.length);
|
|
1584
|
+
for (let i = 0; i < arraySigDataToPass.length; i++) {
|
|
1585
|
+
typedSigArray[i] = arraySigDataToPass[i];
|
|
1586
|
+
}
|
|
1587
|
+
var txnHashReturn = TxnHash2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext, typedPkArray, typedSigArray)
|
|
1588
|
+
if (txnHashReturn && txnHashReturn.error) {
|
|
1589
|
+
return null;
|
|
1590
|
+
}
|
|
1591
|
+
return txnHashReturn.result;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
function transactionGetData2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext, pkkey, sig) {
|
|
1595
|
+
const arrayPkDataToPass = pkkey.toString().split(",");
|
|
1596
|
+
const typedPkArray = new Uint8Array(arrayPkDataToPass.length);
|
|
1597
|
+
for (let i = 0; i < arrayPkDataToPass.length; i++) {
|
|
1598
|
+
typedPkArray[i] = arrayPkDataToPass[i];
|
|
1599
|
+
}
|
|
1600
|
+
const arraySigDataToPass = sig.toString().split(",");
|
|
1601
|
+
const typedSigArray = new Uint8Array(arraySigDataToPass.length);
|
|
1602
|
+
for (let i = 0; i < arraySigDataToPass.length; i++) {
|
|
1603
|
+
typedSigArray[i] = arraySigDataToPass[i];
|
|
1604
|
+
}
|
|
1605
|
+
var txnDataReturn = TxnData2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext, typedPkArray, typedSigArray)
|
|
1606
|
+
if (txnDataReturn && txnDataReturn.error) {
|
|
1607
|
+
return null;
|
|
1608
|
+
}
|
|
1609
|
+
return txnDataReturn.result;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
/**
|
|
1613
|
+
* The postTransaction function posts a signed transaction to the blockchain.
|
|
1614
|
+
* This method can be used in conjunction with the signSendCoinTransaction method to submit a transaction that was signed using a cold wallet (offline or disconnected or air-gapped wallet).
|
|
1615
|
+
*
|
|
1616
|
+
* @async
|
|
1617
|
+
* @function postTransaction
|
|
1618
|
+
* @param {string} txnData - A signed transaction string returned by the signSendCoinTransaction function.
|
|
1619
|
+
* @return {Promise<SendResult>} Returns a promise of type SendResult. txnHash will be null in SendResult.
|
|
1620
|
+
*/
|
|
1621
|
+
async function postTransaction(txnData) {
|
|
1622
|
+
if (isInitialized === false) {
|
|
1623
|
+
return -1000;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
if (txnData == null) {
|
|
1627
|
+
return new SendResult(-600, null, null, null);
|
|
1628
|
+
}
|
|
1629
|
+
var url = config.writeUrl + "/transactions";
|
|
1630
|
+
|
|
1631
|
+
let requestId = getRandomRequestId();
|
|
1632
|
+
|
|
1633
|
+
let reqHeaders = new Headers({
|
|
1634
|
+
"Content-Type": "application/json"
|
|
1635
|
+
});
|
|
1636
|
+
reqHeaders.append(REQUEST_ID_HEADER_NAME, requestId);
|
|
1637
|
+
if (config.writeApiKey !== null) {
|
|
1638
|
+
reqHeaders.append(API_KEY_HEADER_NAME, config.writeApiKey); }
|
|
1639
|
+
|
|
1640
|
+
|
|
1641
|
+
let txnDataJson = JSON.stringify({ txnData: txnData });
|
|
1642
|
+
|
|
1643
|
+
try {
|
|
1644
|
+
const response = await fetch(url, {
|
|
1645
|
+
method: 'POST',
|
|
1646
|
+
headers: reqHeaders,
|
|
1647
|
+
body: txnDataJson
|
|
1648
|
+
});
|
|
1649
|
+
|
|
1650
|
+
if (response == null) {
|
|
1651
|
+
return new SendResult(-601, null, null, requestId);
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
if (response.status === 200 || response.status === 204) {
|
|
1655
|
+
return new SendResult(0, null, response, requestId);
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
return new SendResult(-602, null, response, requestId);
|
|
1659
|
+
} catch(error) {
|
|
1660
|
+
return new SendResult(-10000, null, null, requestId, error);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
/**
|
|
1665
|
+
* The getLatestBlockDetails function returns details of the latest block of the blockchain.
|
|
1666
|
+
*
|
|
1667
|
+
* @async
|
|
1668
|
+
* @function getLatestBlockDetails
|
|
1669
|
+
* @return {Promise<LatestBlockDetailsResult>} Returns a promise of an object of type LatestBlockDetailsResult.
|
|
1670
|
+
*/
|
|
1671
|
+
async function getLatestBlockDetails() {
|
|
1672
|
+
if (isInitialized === false) {
|
|
1673
|
+
return -1000;
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
let requestId = getRandomRequestId();
|
|
1677
|
+
|
|
1678
|
+
let reqHeaders = new Headers({
|
|
1679
|
+
"Content-Type": "application/json"
|
|
1680
|
+
});
|
|
1681
|
+
reqHeaders.append(REQUEST_ID_HEADER_NAME, requestId);
|
|
1682
|
+
if (config.readApiKey !== null) {
|
|
1683
|
+
reqHeaders.append(API_KEY_HEADER_NAME, config.readApiKey);
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
var url = config.readUrl + "/latestblock";
|
|
1687
|
+
|
|
1688
|
+
try {
|
|
1689
|
+
const response = await fetch(url, {
|
|
1690
|
+
headers: reqHeaders,
|
|
1691
|
+
});
|
|
1692
|
+
|
|
1693
|
+
if (response == null) {
|
|
1694
|
+
return new LatestBlockDetailsResult(-100, null, response, requestId);
|
|
1695
|
+
}
|
|
1696
|
+
if (response.status !== 200) {
|
|
1697
|
+
return new LatestBlockDetailsResult(-101, null, response, requestId);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
const jsonObj = await response.json();
|
|
1701
|
+
if (jsonObj == null) {
|
|
1702
|
+
return new LatestBlockDetailsResult(-102, null, response, requestId);
|
|
1703
|
+
}
|
|
1704
|
+
const result = jsonObj.result;
|
|
1705
|
+
|
|
1706
|
+
if (result == null) {
|
|
1707
|
+
return new LatestBlockDetailsResult(-103, null, response, requestId);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
if (result.blockNumber == null) {
|
|
1711
|
+
return new LatestBlockDetailsResult(-104, null, response, requestId);
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
let blockNumber = parseInt(result.blockNumber);
|
|
1715
|
+
if (Number.isInteger(blockNumber) === false) {
|
|
1716
|
+
return new LatestBlockDetailsResult(-105, null, response, requestId);
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
var blockDetails = new BlockDetails(blockNumber);
|
|
1720
|
+
return new LatestBlockDetailsResult(0, blockDetails, response, requestId);
|
|
1721
|
+
} catch (error) {
|
|
1722
|
+
return new LatestBlockDetailsResult(-10000, null, null, requestId, error);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
/**
|
|
1727
|
+
* The getAccountDetails function returns details of an account corresponding to the address.
|
|
1728
|
+
*
|
|
1729
|
+
* @async
|
|
1730
|
+
* @function getAccountDetails
|
|
1731
|
+
* @param {string} address - The address of the account of which the details have to be retrieved.
|
|
1732
|
+
* @return {Promise<AccountDetailsResult>} Returns a promise of type AccountDetailsResult.
|
|
1733
|
+
*/
|
|
1734
|
+
async function getAccountDetails(address) {
|
|
1735
|
+
if (isInitialized === false) {
|
|
1736
|
+
return -1000;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
if (address == null) {
|
|
1740
|
+
return new AccountDetailsResult(-200, null, null, null);
|
|
1741
|
+
}
|
|
1742
|
+
if (isAddressValid(address) === false) {
|
|
1743
|
+
return new AccountDetailsResult(-201, null, null, null);
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
let nonce = 0;
|
|
1747
|
+
let balance = "0";
|
|
1748
|
+
let requestId = getRandomRequestId();
|
|
1749
|
+
|
|
1750
|
+
let reqHeaders = new Headers({
|
|
1751
|
+
"Content-Type": "application/json"
|
|
1752
|
+
});
|
|
1753
|
+
reqHeaders.append(REQUEST_ID_HEADER_NAME, requestId);
|
|
1754
|
+
if(config.readApiKey !== null) {
|
|
1755
|
+
reqHeaders.append(API_KEY_HEADER_NAME, config.readApiKey);
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
var url = config.readUrl + "/account/" + address;
|
|
1759
|
+
|
|
1760
|
+
try {
|
|
1761
|
+
const response = await fetch(url, {
|
|
1762
|
+
headers: reqHeaders,
|
|
1763
|
+
});
|
|
1764
|
+
|
|
1765
|
+
if(response == null) {
|
|
1766
|
+
return new AccountDetailsResult(-202, null, response, requestId);
|
|
1767
|
+
}
|
|
1768
|
+
if (response.status !== 200) {
|
|
1769
|
+
return new AccountDetailsResult(-203, null, response, requestId);
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
const jsonObj = await response.json();
|
|
1773
|
+
if (jsonObj == null) {
|
|
1774
|
+
return new AccountDetailsResult(-204, null, response, requestId);
|
|
1775
|
+
}
|
|
1776
|
+
const result = jsonObj.result;
|
|
1777
|
+
|
|
1778
|
+
if (result == null) {
|
|
1779
|
+
return new AccountDetailsResult(-205, null, response, requestId);
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
if(result.blockNumber == null) {
|
|
1783
|
+
return new AccountDetailsResult(-206, null, response, requestId);
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
let blockNumber = parseInt(result.blockNumber);
|
|
1787
|
+
if (Number.isInteger(blockNumber) === false) {
|
|
1788
|
+
return new AccountDetailsResult(-207, null, response, requestId);
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
if (result.nonce === null) {
|
|
1792
|
+
nonce = 0;
|
|
1793
|
+
} else {
|
|
1794
|
+
let tempNonce = parseInt(result.nonce);
|
|
1795
|
+
if (Number.isInteger(tempNonce) === true) {
|
|
1796
|
+
nonce = tempNonce;
|
|
1797
|
+
if (nonce < 0) {
|
|
1798
|
+
return new AccountDetailsResult(-208, null, response, requestId);
|
|
1799
|
+
}
|
|
1800
|
+
} else {
|
|
1801
|
+
return new AccountDetailsResult(-209, null, response, requestId);
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
if (result.balance != null) {
|
|
1806
|
+
if (isLargeNumber(result.balance) === false) {
|
|
1807
|
+
return new AccountDetailsResult(-210, null, response, requestId);
|
|
1808
|
+
} else {
|
|
1809
|
+
balance = result.balance;
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
var accountDetails = new AccountDetails(address, balance, nonce, blockNumber);
|
|
1814
|
+
return new AccountDetailsResult(0, accountDetails, response, requestId);
|
|
1815
|
+
|
|
1816
|
+
} catch (error) {
|
|
1817
|
+
return new AccountDetailsResult(-10000, null, null, requestId, error);
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
/**
|
|
1822
|
+
* The getTransactionDetails function returns details of a transaction posted to the blockchain.
|
|
1823
|
+
* Transactions may take a while to get registered in the blockchain. After a transaction is submitted, it may take a while before it is available for reading.
|
|
1824
|
+
* Some transactions that have lower balance than the minimum required for gas fees may be discarded.
|
|
1825
|
+
* In these cases, the transactions may not be returned when invoking the getTransactionDetails function.
|
|
1826
|
+
* You should consider the transaction as succeeded only if the status field of the transactionReceipt object is 0x1 (success).
|
|
1827
|
+
* The transactionReceipt field can be null unless the transaction is registered with the blockchain.
|
|
1828
|
+
* @async
|
|
1829
|
+
* @function getTransactionDetails
|
|
1830
|
+
* @param {string} txnHash - The hash of the transaction to retrieve.
|
|
1831
|
+
* @return {Promise<TransactionDetailsResult>} Returns a promise of type TransactionDetailsResult.
|
|
1832
|
+
*/
|
|
1833
|
+
async function getTransactionDetails(txnHash) {
|
|
1834
|
+
if (isInitialized === false) {
|
|
1835
|
+
return -1000;
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
if (txnHash == null) {
|
|
1839
|
+
return new TransactionDetailsResult(-300, null, null, null);
|
|
1840
|
+
}
|
|
1841
|
+
if (isAddressValid(txnHash) === false) {
|
|
1842
|
+
return new TransactionDetailsResult(-301, null, null, null);
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
let requestId = getRandomRequestId();
|
|
1846
|
+
|
|
1847
|
+
let reqHeaders = new Headers({
|
|
1848
|
+
"Content-Type": "application/json"
|
|
1849
|
+
});
|
|
1850
|
+
reqHeaders.append(REQUEST_ID_HEADER_NAME, requestId);
|
|
1851
|
+
if (config.readApiKey !== null) {
|
|
1852
|
+
reqHeaders.append(API_KEY_HEADER_NAME, config.readApiKey);
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
var url = config.readUrl + "/transaction/" + txnHash;
|
|
1856
|
+
|
|
1857
|
+
try {
|
|
1858
|
+
const response = await fetch(url, {
|
|
1859
|
+
headers: reqHeaders,
|
|
1860
|
+
});
|
|
1861
|
+
|
|
1862
|
+
if (response == null) {
|
|
1863
|
+
return new TransactionDetailsResult(-302, null, response, requestId);
|
|
1864
|
+
}
|
|
1865
|
+
if (response.status !== 200) {
|
|
1866
|
+
return new TransactionDetailsResult(-303, null, response, requestId);
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
const jsonObj = await response.json();
|
|
1870
|
+
if (jsonObj == null) {
|
|
1871
|
+
return new TransactionDetailsResult(-304, null, response, requestId);
|
|
1872
|
+
}
|
|
1873
|
+
const result = jsonObj.result;
|
|
1874
|
+
|
|
1875
|
+
if (result == null) {
|
|
1876
|
+
return new TransactionDetailsResult(-305, null, response, requestId);
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
var transactionDetails = new TransactionDetails();
|
|
1880
|
+
|
|
1881
|
+
if (result.blockNumber !== null) {
|
|
1882
|
+
let tempBlockNumber = parseInt(result.blockNumber);
|
|
1883
|
+
if (Number.isInteger(tempBlockNumber) === true) {
|
|
1884
|
+
transactionDetails.blockNumber = tempBlockNumber;
|
|
1885
|
+
}
|
|
1886
|
+
if (tempBlockNumber < 0) {
|
|
1887
|
+
return new TransactionDetailsResult(-306, null, response, requestId);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
transactionDetails.blockHash = result.blockHash;
|
|
1892
|
+
transactionDetails.from = result.from;
|
|
1893
|
+
transactionDetails.gas = result.gas;
|
|
1894
|
+
transactionDetails.gasPrice = result.gasPrice;
|
|
1895
|
+
transactionDetails.hash = result.hash;
|
|
1896
|
+
transactionDetails.input = result.input;
|
|
1897
|
+
transactionDetails.nonce = result.nonce;
|
|
1898
|
+
transactionDetails.to = result.to;
|
|
1899
|
+
transactionDetails.value = result.value;
|
|
1900
|
+
|
|
1901
|
+
if(result.receipt !== null) {
|
|
1902
|
+
transactionDetails.receipt = new TransactionReceipt();
|
|
1903
|
+
transactionDetails.receipt.cumulativeGasUsed = result.receipt.cumulativeGasUsed;
|
|
1904
|
+
transactionDetails.receipt.effectiveGasPrice = result.receipt.effectiveGasPrice;
|
|
1905
|
+
transactionDetails.receipt.gasUsed = result.receipt.gasUsed;
|
|
1906
|
+
transactionDetails.receipt.status = result.receipt.status;
|
|
1907
|
+
transactionDetails.receipt.hash = result.receipt.hash;
|
|
1908
|
+
transactionDetails.receipt.type = result.receipt.type;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
return new TransactionDetailsResult(0, transactionDetails, response, requestId);
|
|
1912
|
+
} catch (error) {
|
|
1913
|
+
return new TransactionDetailsResult(-10000, null, null, requestId, error);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
/**
|
|
1918
|
+
* The listAccountTransactions function returns a list of transactions for a specific account.
|
|
1919
|
+
* Transactions may take a while to get registered in the blockchain. After a transaction is submitted, it may take a while before it is available for listing.
|
|
1920
|
+
* Some transactions that have lower balance than the minimum required for gas fees may be discarded.
|
|
1921
|
+
* In these cases, the transactions may not be returned when invoking the listAccountTransactions function.
|
|
1922
|
+
* You should consider the transaction as succeeded only if the status field of the AccountTransactionCompact object is 0x1 (success).
|
|
1923
|
+
* Both transactions from and transactions to the address will be returned in the list.
|
|
1924
|
+
* Use the getTransactionDetails function, passing the hash of the transaction to get detailed information about the transaction.
|
|
1925
|
+
* @async
|
|
1926
|
+
* @function listAccountTransactions
|
|
1927
|
+
* @param {string} address - The address for which the transactions have to be listed.
|
|
1928
|
+
* @param {number} pageNumber - The page number for which the transactions has to be listed for the account. Pass 0 to list the latest page. Pass 1 to list the oldest page. A maximum of 20 transactions are returned in each page. The response of this API includes a field that shows the pageCount (total number of pages available). You can pass any number between 1 to pageCount to get the corresponding page.
|
|
1929
|
+
* @return {Promise<AccountTransactionsResult>} Returns a promise of type AccountTransactionsResult.
|
|
1930
|
+
*/
|
|
1931
|
+
async function listAccountTransactions(address, pageNumber) {
|
|
1932
|
+
if (isInitialized === false) {
|
|
1933
|
+
return -1000;
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
if (address === null) {
|
|
1937
|
+
return new AccountTransactionsResult(-700, null, null, null);
|
|
1938
|
+
}
|
|
1939
|
+
if (isAddressValid(address) === false) {
|
|
1940
|
+
return new AccountTransactionsResult(-701, null, null, null);
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
if (pageNumber === null) {
|
|
1944
|
+
pageNumber = 0;
|
|
1945
|
+
} else if (Number.isInteger(pageNumber) === false) {
|
|
1946
|
+
return new AccountTransactionsResult(-702, null, null, null);
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
let requestId = getRandomRequestId();
|
|
1950
|
+
|
|
1951
|
+
let reqHeaders = new Headers({
|
|
1952
|
+
"Content-Type": "application/json"
|
|
1953
|
+
});
|
|
1954
|
+
reqHeaders.append(REQUEST_ID_HEADER_NAME, requestId);
|
|
1955
|
+
if (config.readApiKey !== null) {
|
|
1956
|
+
reqHeaders.append(API_KEY_HEADER_NAME, config.readApiKey);
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
var url = config.readUrl + "/account/" + address + "/transactions/" + pageNumber;
|
|
1960
|
+
|
|
1961
|
+
try {
|
|
1962
|
+
const response = await fetch(url, {
|
|
1963
|
+
headers: reqHeaders,
|
|
1964
|
+
});
|
|
1965
|
+
|
|
1966
|
+
if (response === null) {
|
|
1967
|
+
return new AccountTransactionsResult(-703, null, response, requestId);
|
|
1968
|
+
}
|
|
1969
|
+
if (response.status !== 200) {
|
|
1970
|
+
return new AccountTransactionsResult(-704, null, response, requestId);
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
const jsonObj = await response.json();
|
|
1974
|
+
|
|
1975
|
+
if (jsonObj === null) {
|
|
1976
|
+
return new AccountTransactionsResult(-705, null, response, requestId);
|
|
1977
|
+
}
|
|
1978
|
+
const result = jsonObj;
|
|
1979
|
+
|
|
1980
|
+
if (result.pageCount === null) {
|
|
1981
|
+
return new AccountTransactionsResult(-706, null, response, requestId);
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
var listAccountDetailsResponse = new ListAccountTransactionsResponse();
|
|
1985
|
+
|
|
1986
|
+
let tempPageCount = parseInt(result.pageCount);
|
|
1987
|
+
if (Number.isInteger(tempPageCount) === true) {
|
|
1988
|
+
listAccountDetailsResponse.pageCount = tempPageCount;
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
if (result.items !== null) {
|
|
1992
|
+
if (Array.isArray(result.items) === false) {
|
|
1993
|
+
return new AccountTransactionsResult(-707, null, response, requestId);
|
|
1994
|
+
}
|
|
1995
|
+
listAccountDetailsResponse.items = new Array();
|
|
1996
|
+
for (const item of result.items) {
|
|
1997
|
+
let txn = new AccountTransactionCompact();
|
|
1998
|
+
txn.blockNumber = item.blockNumber;
|
|
1999
|
+
txn.from = item.from;
|
|
2000
|
+
txn.hash = item.hash;
|
|
2001
|
+
txn.to = item.to;
|
|
2002
|
+
txn.value = item.value;
|
|
2003
|
+
txn.status = item.status;
|
|
2004
|
+
listAccountDetailsResponse.items.push(txn);
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
return new AccountTransactionsResult(0, listAccountDetailsResponse, response, requestId);
|
|
2009
|
+
} catch (error) {
|
|
2010
|
+
return new AccountTransactionsResult(-10000, null, null, requestId, error);
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
/**
|
|
2015
|
+
* The signSendCoinTransaction function returns a signed transaction. The chainId used for signing should be provided in the initialize() function.
|
|
2016
|
+
* Since the gas fee for sending coins is fixed at 1000 coins, there is no option to set the gas fee explicitly.
|
|
2017
|
+
* This function is useful for offline (cold storage) wallets, where you can sign a transaction offline and then use the postTransaction function to post it on a connected device.
|
|
2018
|
+
* Another usecase for this function is when you want to first store a signed transaction to a database, then queue it and finally submit the transaction by calling the postTransaction function.
|
|
2019
|
+
*
|
|
2020
|
+
* @deprecated Use signRawTransaction instead.
|
|
2021
|
+
* @function signSendCoinTransaction
|
|
2022
|
+
* @param {Wallet} wallet - A Wallet object from which the transaction has to be sent. The address corresponding to the Wallet should have enough coins to cover gas fees as well. A minimum of 1000 coins (1000000000000000000000 wei) are required for gas fees.
|
|
2023
|
+
* @param {string} toAddress - The address to which the coins should be sent.
|
|
2024
|
+
* @param {string} coins - The string representing the number of coins (in ether) to send. To convert between ethers and wei, see https://docs.ethers.org/v4/api-utils.html#ether-strings-and-wei
|
|
2025
|
+
* @param {number} nonce - The nonce of the account retrieved by invoking the getAccountDetails function. You have to carefully manage state of the nonce to avoid sending the coins multiple times, such as when retrying sendCoins after a network error.
|
|
2026
|
+
* @return {Promise<SignResult>} Returns a promise of type SignResult.
|
|
2027
|
+
*/
|
|
2028
|
+
async function signSendCoinTransaction(wallet, toAddress, coins, nonce) {
|
|
2029
|
+
if (isInitialized === false) {
|
|
2030
|
+
return -1000;
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
if (wallet == null || toAddress == null || coins == null || nonce == null) {
|
|
2034
|
+
return new SignResult(-500, null, null);
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
if (isAddressValid(toAddress) === false) {
|
|
2038
|
+
return new SignResult(-501, null, null);
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
if (verifyWallet(wallet) === false) {
|
|
2042
|
+
return new SignResult(-502, null, null);
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
if (isLargeNumber(coins) === false) {
|
|
2046
|
+
return new SignResult(-503, null, null);
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
let tempNonce = parseInt(nonce);
|
|
2050
|
+
if (Number.isInteger(tempNonce) === false) {
|
|
2051
|
+
return new SignResult(-504, null, null);
|
|
2052
|
+
}
|
|
2053
|
+
nonce = tempNonce;
|
|
2054
|
+
if (nonce < 0) {
|
|
2055
|
+
return new SignResult(-505, null, null);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
const contractData = null;
|
|
2059
|
+
|
|
2060
|
+
var txSigningHash = transactionGetSigningHash(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData);
|
|
2061
|
+
if (txSigningHash == null) {
|
|
2062
|
+
return new SignResult(-506, null, null);
|
|
2063
|
+
}
|
|
2064
|
+
const txSigningHashU8 = toUint8Array(txSigningHash);
|
|
2065
|
+
const hybridedsNs = circl && circl.hybrideds;
|
|
2066
|
+
if (!hybridedsNs) {
|
|
2067
|
+
return new SignResult(-507, null, null);
|
|
2068
|
+
}
|
|
2069
|
+
const sigRes = hybridedsNs.signCompact(toUint8Array(wallet.privateKey), txSigningHashU8);
|
|
2070
|
+
if (sigRes && sigRes.error) {
|
|
2071
|
+
return new SignResult(-507, null, null);
|
|
2072
|
+
}
|
|
2073
|
+
const verRes = hybridedsNs.verifyCompact(toUint8Array(wallet.publicKey), txSigningHashU8, sigRes.result);
|
|
2074
|
+
if (verRes && verRes.error) {
|
|
2075
|
+
return new SignResult(-507, null, null);
|
|
2076
|
+
}
|
|
2077
|
+
if (verRes.result !== true) {
|
|
2078
|
+
return new SignResult(-507, null, null);
|
|
2079
|
+
}
|
|
2080
|
+
const quantumSig = sigRes.result instanceof Uint8Array ? Array.from(sigRes.result) : sigRes.result;
|
|
2081
|
+
|
|
2082
|
+
var txHashHex = transactionGetTransactionHash(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData, wallet.publicKey, quantumSig);
|
|
2083
|
+
if (txHashHex == null) {
|
|
2084
|
+
return new SignResult(-508, null, null);
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
var txnData = transactionGetData(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData, wallet.publicKey, quantumSig);
|
|
2088
|
+
if (txnData == null) {
|
|
2089
|
+
return new SignResult(-509, null, null);
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
return new SignResult(0, txHashHex, txnData);
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
/**
|
|
2096
|
+
* The signTransaction function returns a signed transaction. The chainId used for signing should be provided in the initialize() function.
|
|
2097
|
+
* Since the gas fee for sending coins is fixed at 1000 coins, there is no option to set the gas fee explicitly.
|
|
2098
|
+
* This function is useful for offline (cold storage) wallets, where you can sign a transaction offline and then use the postTransaction function to post it on a connected device.
|
|
2099
|
+
* Another usecase for this function is when you want to first store a signed transaction to a database, then queue it and finally submit the transaction by calling the postTransaction function.
|
|
2100
|
+
*
|
|
2101
|
+
* @deprecated Use signRawTransaction instead.
|
|
2102
|
+
* @function signTransaction
|
|
2103
|
+
* @param {Wallet} wallet - A Wallet object from which the transaction has to be sent. The address corresponding to the Wallet should have enough coins to cover gas fees as well. A minimum of 1000 coins (1000000000000000000000 wei) are required for gas fees.
|
|
2104
|
+
* @param {string} toAddress - The address to which the coins should be sent.
|
|
2105
|
+
* @param {string} coins - The string representing the number of coins (in ether) to send. To convert between ethers and wei, see https://docs.ethers.org/v4/api-utils.html#ether-strings-and-wei
|
|
2106
|
+
* @param {number} nonce - The nonce of the account retrieved by invoking the getAccountDetails function. You have to carefully manage state of the nonce to avoid sending the coins multiple times, such as when retrying sendCoins after a network error.
|
|
2107
|
+
* @param {string} data - Ignored. This parameter is accepted but not used. Use signRawTransaction to pass contract data.
|
|
2108
|
+
* @return {Promise<SignResult>} Returns a promise of type SignResult.
|
|
2109
|
+
*/
|
|
2110
|
+
async function signTransaction(wallet, toAddress, coins, nonce, data) {
|
|
2111
|
+
if (isInitialized === false) {
|
|
2112
|
+
return -1000;
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
if (wallet == null || toAddress == null || coins == null || nonce == null) {
|
|
2116
|
+
return new SignResult(-500, null, null);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
if (isAddressValid(toAddress) === false) {
|
|
2120
|
+
return new SignResult(-501, null, null);
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
if (verifyWallet(wallet) === false) {
|
|
2124
|
+
return new SignResult(-502, null, null);
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
if (isLargeNumber(coins) === false) {
|
|
2128
|
+
return new SignResult(-503, null, null);
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
let tempNonce = parseInt(nonce);
|
|
2132
|
+
if (Number.isInteger(tempNonce) === false) {
|
|
2133
|
+
return new SignResult(-504, null, null);
|
|
2134
|
+
}
|
|
2135
|
+
nonce = tempNonce;
|
|
2136
|
+
if (nonce < 0) {
|
|
2137
|
+
return new SignResult(-505, null, null);
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
const contractData = null;
|
|
2141
|
+
|
|
2142
|
+
var txSigningHash = transactionGetSigningHash(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData);
|
|
2143
|
+
if (txSigningHash == null) {
|
|
2144
|
+
return new SignResult(-506, null, null);
|
|
2145
|
+
}
|
|
2146
|
+
const txSigningHashU8 = toUint8Array(txSigningHash);
|
|
2147
|
+
const hybridedsNs = circl && circl.hybrideds;
|
|
2148
|
+
if (!hybridedsNs) {
|
|
2149
|
+
return new SignResult(-507, null, null);
|
|
2150
|
+
}
|
|
2151
|
+
const sigRes = hybridedsNs.signCompact(toUint8Array(wallet.privateKey), txSigningHashU8);
|
|
2152
|
+
if (sigRes && sigRes.error) {
|
|
2153
|
+
return new SignResult(-507, null, null);
|
|
2154
|
+
}
|
|
2155
|
+
const verRes = hybridedsNs.verifyCompact(toUint8Array(wallet.publicKey), txSigningHashU8, sigRes.result);
|
|
2156
|
+
if (verRes && verRes.error) {
|
|
2157
|
+
return new SignResult(-507, null, null);
|
|
2158
|
+
}
|
|
2159
|
+
if (verRes.result !== true) {
|
|
2160
|
+
return new SignResult(-507, null, null);
|
|
2161
|
+
}
|
|
2162
|
+
const quantumSig = sigRes.result instanceof Uint8Array ? Array.from(sigRes.result) : sigRes.result;
|
|
2163
|
+
|
|
2164
|
+
var txHashHex = transactionGetTransactionHash(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData, wallet.publicKey, quantumSig);
|
|
2165
|
+
if (txHashHex == null) {
|
|
2166
|
+
return new SignResult(-508, null, null);
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
var txnData = transactionGetData(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData, wallet.publicKey, quantumSig);
|
|
2170
|
+
if (txnData == null) {
|
|
2171
|
+
return new SignResult(-509, null, null);
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
return new SignResult(0, txHashHex, txnData);
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
/**
|
|
2178
|
+
* Helper function to convert a hex string to Uint8Array
|
|
2179
|
+
* @param {string} hex - Hex string with or without 0x prefix
|
|
2180
|
+
* @return {Uint8Array} Uint8Array representation of the hex string, or empty array if null/undefined
|
|
2181
|
+
*/
|
|
2182
|
+
function hexStringToUint8Array(hex) {
|
|
2183
|
+
// Return empty array if null or undefined
|
|
2184
|
+
if (hex === null || hex === undefined) {
|
|
2185
|
+
return new Uint8Array(0);
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
// Remove 0x prefix if present
|
|
2189
|
+
if (hex.startsWith('0x')) {
|
|
2190
|
+
hex = hex.slice(2);
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
if (/[^0-9a-fA-F]/.test(hex)) {
|
|
2194
|
+
return new Uint8Array(0);
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
// Ensure even length (pad with leading zero if needed)
|
|
2198
|
+
if (hex.length % 2 !== 0) {
|
|
2199
|
+
hex = '0' + hex;
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
// Convert hex string to Uint8Array
|
|
2203
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
2204
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
2205
|
+
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
return bytes;
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
/**
|
|
2212
|
+
* The signRawTransaction function returns a signed transaction. The chainId used for signing can be provided in the TransactionSigningRequest, or if null, the chainId specified in the initialize() function will be used.
|
|
2213
|
+
* With this function, you can set the gasLimit explicitly compared to signTransaction.
|
|
2214
|
+
* You can also pass data to be signed, such as when creating or invoking a smart contract.
|
|
2215
|
+
* Since the gas fee is fixed at 1000 coins for 21000 units of gas, there is no option to set the gas fee explicitly.
|
|
2216
|
+
* This function is useful for offline (cold storage) wallets, where you can sign a transaction offline and then use the postTransaction function to post it on a connected device.
|
|
2217
|
+
* Another usecase for this function is when you want to first store a signed transaction to a database, then queue it and finally submit the transaction by calling the postTransaction function.
|
|
2218
|
+
*
|
|
2219
|
+
* @function signRawTransaction
|
|
2220
|
+
* @param {TransactionSigningRequest} transactionSigningRequest - An object of type TransactionSigningRequest with the transaction signing details.
|
|
2221
|
+
* @return {SignResult} Returns a promise of type SignResult.
|
|
2222
|
+
*/
|
|
2223
|
+
function signRawTransaction(transactionSigningRequest) {
|
|
2224
|
+
if (isInitialized === false) {
|
|
2225
|
+
return -1000;
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
if (transactionSigningRequest.wallet == null || transactionSigningRequest.nonce == null || transactionSigningRequest.gasLimit == null) {
|
|
2229
|
+
return new SignResult(-900, null, null);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
if (transactionSigningRequest.toAddress !== null && isAddressValid(transactionSigningRequest.toAddress) === false) {
|
|
2233
|
+
return new SignResult(-901, null, null);
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
if (verifyWallet(transactionSigningRequest.wallet) === false) {
|
|
2237
|
+
return new SignResult(-902, null, null);
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
// Convert valueInWei to hex if needed
|
|
2241
|
+
let valueInWeiHex = null;
|
|
2242
|
+
if (transactionSigningRequest.valueInWei !== null) {
|
|
2243
|
+
if (typeof transactionSigningRequest.valueInWei === 'bigint') {
|
|
2244
|
+
// Convert BigInt to hex string
|
|
2245
|
+
valueInWeiHex = '0x' + transactionSigningRequest.valueInWei.toString(16);
|
|
2246
|
+
} else if (typeof transactionSigningRequest.valueInWei === 'string') {
|
|
2247
|
+
if (transactionSigningRequest.valueInWei.startsWith('0x') === false || /[^0-9a-fA-F]/.test(transactionSigningRequest.valueInWei.slice(2))) {
|
|
2248
|
+
return new SignResult(-903, null, null);
|
|
2249
|
+
}
|
|
2250
|
+
valueInWeiHex = transactionSigningRequest.valueInWei;
|
|
2251
|
+
} else {
|
|
2252
|
+
return new SignResult(-923, null, null);
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
let tempNonce = parseInt(transactionSigningRequest.nonce);
|
|
2257
|
+
if (Number.isInteger(tempNonce) === false) {
|
|
2258
|
+
return new SignResult(-904, null, null);
|
|
2259
|
+
}
|
|
2260
|
+
let nonce = tempNonce;
|
|
2261
|
+
if (nonce < 0) {
|
|
2262
|
+
return new SignResult(-905, null, null);
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
let data = null;
|
|
2266
|
+
if (transactionSigningRequest.data !== null) {
|
|
2267
|
+
if (typeof transactionSigningRequest.data !== 'string' || transactionSigningRequest.data.startsWith('0x') === false || /[^0-9a-fA-F]/.test(transactionSigningRequest.data.slice(2))) {
|
|
2268
|
+
return new SignResult(-906, null, null);
|
|
2269
|
+
}
|
|
2270
|
+
data = hexStringToUint8Array(transactionSigningRequest.data);
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
let tempGasLimit = parseInt(transactionSigningRequest.gasLimit);
|
|
2274
|
+
if (Number.isInteger(tempGasLimit) === false) {
|
|
2275
|
+
return new SignResult(-907, null, null);
|
|
2276
|
+
}
|
|
2277
|
+
let gasLimit = tempGasLimit;
|
|
2278
|
+
if (gasLimit < 0) {
|
|
2279
|
+
return new SignResult(-908, null, null);
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
let remarks = null;
|
|
2283
|
+
if (transactionSigningRequest.remarks !== null) {
|
|
2284
|
+
if (typeof transactionSigningRequest.remarks !== 'string' || transactionSigningRequest.remarks.startsWith('0x') === false || /[^0-9a-fA-F]/.test(transactionSigningRequest.remarks.slice(2))) {
|
|
2285
|
+
return new SignResult(-909, null, null);
|
|
2286
|
+
}
|
|
2287
|
+
remarks = hexStringToUint8Array(transactionSigningRequest.remarks);
|
|
2288
|
+
if (remarks.length > 32) {
|
|
2289
|
+
return new SignResult(-910, null, null);
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
|
|
2293
|
+
// Use chainId from request if provided, otherwise use the one from initialize()
|
|
2294
|
+
let chainId;
|
|
2295
|
+
if (transactionSigningRequest.chainId !== null && transactionSigningRequest.chainId !== undefined) {
|
|
2296
|
+
// Validate chainId if provided
|
|
2297
|
+
let tempChainId = parseInt(transactionSigningRequest.chainId);
|
|
2298
|
+
if (Number.isInteger(tempChainId) === false) {
|
|
2299
|
+
return new SignResult(-911, null, null);
|
|
2300
|
+
}
|
|
2301
|
+
chainId = tempChainId;
|
|
2302
|
+
if (chainId < 0) {
|
|
2303
|
+
return new SignResult(-912, null, null);
|
|
2304
|
+
}
|
|
2305
|
+
} else {
|
|
2306
|
+
// Use chainId from initialize()
|
|
2307
|
+
chainId = config.chainId;
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
let signingContext = transactionSigningRequest.signingContext;
|
|
2311
|
+
const keyTypeForContext = getKeyTypeFromPrivateKey(transactionSigningRequest.wallet.privateKey);
|
|
2312
|
+
if (signingContext === null || signingContext === undefined) {
|
|
2313
|
+
if (keyTypeForContext === KEY_TYPE_HYBRIDEDMLDSASLHDSA) {
|
|
2314
|
+
signingContext = 0;
|
|
2315
|
+
} else if (keyTypeForContext === KEY_TYPE_HYBRIDEDMLDSASLHDSA5) {
|
|
2316
|
+
signingContext = 1;
|
|
2317
|
+
} else {
|
|
2318
|
+
return new SignResult(-913, null, null);
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
let txSigningHash = transactionGetSigningHash2(transactionSigningRequest.wallet.address, nonce, transactionSigningRequest.toAddress, valueInWeiHex, gasLimit, chainId, data, remarks, signingContext);
|
|
2323
|
+
if (txSigningHash == null) {
|
|
2324
|
+
return new SignResult(-914, null, null);
|
|
2325
|
+
}
|
|
2326
|
+
const txSigningHashU8 = toUint8Array(txSigningHash);
|
|
2327
|
+
const wallet = transactionSigningRequest.wallet;
|
|
2328
|
+
const privU8 = toUint8Array(wallet.privateKey);
|
|
2329
|
+
const pubU8 = toUint8Array(wallet.publicKey);
|
|
2330
|
+
let sigRes;
|
|
2331
|
+
let verRes;
|
|
2332
|
+
const hybridNs = circl && circl.hybridedmldsaslhdsa;
|
|
2333
|
+
const hybrid5Ns = circl && (circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5);
|
|
2334
|
+
if (signingContext === 0 && hybridNs) {
|
|
2335
|
+
sigRes = hybridNs.signCompact(privU8, txSigningHashU8);
|
|
2336
|
+
if (sigRes && sigRes.error) return new SignResult(-915, null, null);
|
|
2337
|
+
verRes = hybridNs.verifyCompact(pubU8, txSigningHashU8, sigRes.result);
|
|
2338
|
+
} else if (signingContext === 1 && hybrid5Ns) {
|
|
2339
|
+
sigRes = hybrid5Ns.sign(privU8, txSigningHashU8);
|
|
2340
|
+
if (sigRes && sigRes.error) return new SignResult(-916, null, null);
|
|
2341
|
+
verRes = hybrid5Ns.verify(pubU8, txSigningHashU8, sigRes.result);
|
|
2342
|
+
} else if (signingContext === 2 && hybridNs) {
|
|
2343
|
+
sigRes = hybridNs.sign(privU8, txSigningHashU8);
|
|
2344
|
+
if (sigRes && sigRes.error) return new SignResult(-917, null, null);
|
|
2345
|
+
verRes = hybridNs.verify(pubU8, txSigningHashU8, sigRes.result);
|
|
2346
|
+
} else {
|
|
2347
|
+
return new SignResult(-918, null, null);
|
|
2348
|
+
}
|
|
2349
|
+
if (verRes && verRes.error) return new SignResult(-919, null, null);
|
|
2350
|
+
if (verRes.result !== true) return new SignResult(-920, null, null);
|
|
2351
|
+
const quantumSig = sigRes.result instanceof Uint8Array ? Array.from(sigRes.result) : sigRes.result;
|
|
2352
|
+
|
|
2353
|
+
let txHashHex = transactionGetTransactionHash2(transactionSigningRequest.wallet.address, nonce, transactionSigningRequest.toAddress, valueInWeiHex, gasLimit, chainId, data, remarks, signingContext, transactionSigningRequest.wallet.publicKey, quantumSig);
|
|
2354
|
+
if (txHashHex == null) {
|
|
2355
|
+
return new SignResult(-921, null, null);
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
let txnData = transactionGetData2(transactionSigningRequest.wallet.address, nonce, transactionSigningRequest.toAddress, valueInWeiHex, gasLimit, chainId, data, remarks, signingContext, transactionSigningRequest.wallet.publicKey, quantumSig);
|
|
2359
|
+
if (txnData == null) {
|
|
2360
|
+
return new SignResult(-922, null, null);
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
return new SignResult(0, txHashHex, txnData);
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
/**
|
|
2367
|
+
* Sign a message with a private key. Optional signingContext selects algorithm (same pattern as signRawTransaction); if null/omitted, derived from private key type.
|
|
2368
|
+
* @param {number[]|Uint8Array} privateKey - Private key bytes.
|
|
2369
|
+
* @param {number[]|Uint8Array} message - Message bytes (e.g. 32-byte hash).
|
|
2370
|
+
* @param {number|null} [signingContext] - Optional. 0 = hybridedmldsaslhdsa compact, 1 = hybridedmldsaslhdsa5, 2 = hybridedmldsaslhdsa full. If null/omitted, derived from private key type.
|
|
2371
|
+
* @returns {{ resultCode: number, signature: Uint8Array|null }} resultCode 0 on success, signature bytes; negative on error (e.g. -1000 not initialized, -700 invalid args, -701 unknown key type, -702/-703 CIRCL sign error, -704 unsupported key type or context).
|
|
2372
|
+
*/
|
|
2373
|
+
function sign(privateKey, message, signingContext) {
|
|
2374
|
+
if (isInitialized === false) {
|
|
2375
|
+
return { resultCode: -1000, signature: null };
|
|
2376
|
+
}
|
|
2377
|
+
if (!isByteArray(privateKey) || !isByteArray(message)) {
|
|
2378
|
+
return { resultCode: -700, signature: null };
|
|
2379
|
+
}
|
|
2380
|
+
const privU8 = toUint8Array(privateKey);
|
|
2381
|
+
const messageU8 = toUint8Array(message);
|
|
2382
|
+
const hybridNs = circl && circl.hybridedmldsaslhdsa;
|
|
2383
|
+
const hybrid5Ns = circl && (circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5);
|
|
2384
|
+
let sigRes;
|
|
2385
|
+
const ctx = signingContext === null || signingContext === undefined ? null : signingContext;
|
|
2386
|
+
if (ctx === null) {
|
|
2387
|
+
const keyType = getKeyTypeFromPrivateKey(privateKey);
|
|
2388
|
+
if (keyType == null) {
|
|
2389
|
+
return { resultCode: -701, signature: null };
|
|
2390
|
+
}
|
|
2391
|
+
if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA && hybridNs) {
|
|
2392
|
+
sigRes = hybridNs.signCompact(privU8, messageU8);
|
|
2393
|
+
if (sigRes && sigRes.error) return { resultCode: -702, signature: null };
|
|
2394
|
+
} else if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5 && hybrid5Ns) {
|
|
2395
|
+
sigRes = hybrid5Ns.sign(privU8, messageU8);
|
|
2396
|
+
if (sigRes && sigRes.error) return { resultCode: -703, signature: null };
|
|
2397
|
+
} else {
|
|
2398
|
+
return { resultCode: -704, signature: null };
|
|
2399
|
+
}
|
|
2400
|
+
} else if (ctx === 0 && hybridNs) {
|
|
2401
|
+
sigRes = hybridNs.signCompact(privU8, messageU8);
|
|
2402
|
+
if (sigRes && sigRes.error) return { resultCode: -702, signature: null };
|
|
2403
|
+
} else if (ctx === 1 && hybrid5Ns) {
|
|
2404
|
+
sigRes = hybrid5Ns.sign(privU8, messageU8);
|
|
2405
|
+
if (sigRes && sigRes.error) return { resultCode: -703, signature: null };
|
|
2406
|
+
} else if (ctx === 2 && hybridNs) {
|
|
2407
|
+
sigRes = hybridNs.sign(privU8, messageU8);
|
|
2408
|
+
if (sigRes && sigRes.error) return { resultCode: -702, signature: null };
|
|
2409
|
+
} else {
|
|
2410
|
+
return { resultCode: -704, signature: null };
|
|
2411
|
+
}
|
|
2412
|
+
const sig = sigRes.result instanceof Uint8Array ? sigRes.result : new Uint8Array(sigRes.result);
|
|
2413
|
+
return { resultCode: 0, signature: sig };
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
/**
|
|
2417
|
+
* Verify a signature over a message with a public key. Algorithm is determined by the first byte of the signature: 1=hybrideds verifyCompact, 2=hybrideds verify, 3=hybridedmldsaslhdsa verifyCompact, 4=hybridedmldsaslhdsa verify, 5=hybridedmldsaslhdsa5 verify.
|
|
2418
|
+
* @param {number[]|Uint8Array} publicKey - Public key bytes.
|
|
2419
|
+
* @param {number[]|Uint8Array} signature - Signature bytes from sign(); first byte selects verify function (1-5).
|
|
2420
|
+
* @param {number[]|Uint8Array} message - Message bytes (same as passed to sign).
|
|
2421
|
+
* @returns {{ resultCode: number, valid: boolean }} resultCode 0 and valid true if signature is valid; negative on error (e.g. -1000 not initialized, -715 invalid args, -717 CIRCL verify error, -719 signature invalid, -718 unknown signature type).
|
|
2422
|
+
*/
|
|
2423
|
+
function verify(publicKey, signature, message) {
|
|
2424
|
+
if (isInitialized === false) {
|
|
2425
|
+
return { resultCode: -1000, valid: false };
|
|
2426
|
+
}
|
|
2427
|
+
if (!isByteArray(publicKey) || !isByteArray(signature) || !isByteArray(message)) {
|
|
2428
|
+
return { resultCode: -715, valid: false };
|
|
2429
|
+
}
|
|
2430
|
+
const sigLen = signature.byteLength !== undefined ? signature.byteLength : signature.length;
|
|
2431
|
+
if (sigLen < 1) {
|
|
2432
|
+
return { resultCode: -715, valid: false };
|
|
2433
|
+
}
|
|
2434
|
+
const sigType = signature[0];
|
|
2435
|
+
const pubU8 = toUint8Array(publicKey);
|
|
2436
|
+
const sigU8 = toUint8Array(signature);
|
|
2437
|
+
const messageU8 = toUint8Array(message);
|
|
2438
|
+
const hybridedsNs = circl && circl.hybrideds;
|
|
2439
|
+
const hybridNs = circl && circl.hybridedmldsaslhdsa;
|
|
2440
|
+
const hybrid5Ns = circl && (circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5);
|
|
2441
|
+
let verRes;
|
|
2442
|
+
if (sigType === 1 && hybridedsNs) {
|
|
2443
|
+
verRes = hybridedsNs.verifyCompact(pubU8, messageU8, sigU8);
|
|
2444
|
+
} else if (sigType === 2 && hybridedsNs) {
|
|
2445
|
+
verRes = hybridedsNs.verify(pubU8, messageU8, sigU8);
|
|
2446
|
+
} else if (sigType === 3 && hybridNs) {
|
|
2447
|
+
verRes = hybridNs.verifyCompact(pubU8, messageU8, sigU8);
|
|
2448
|
+
} else if (sigType === 4 && hybridNs) {
|
|
2449
|
+
verRes = hybridNs.verify(pubU8, messageU8, sigU8);
|
|
2450
|
+
} else if (sigType === 5 && hybrid5Ns) {
|
|
2451
|
+
verRes = hybrid5Ns.verify(pubU8, messageU8, sigU8);
|
|
2452
|
+
} else {
|
|
2453
|
+
return { resultCode: -718, valid: false };
|
|
2454
|
+
}
|
|
2455
|
+
if (verRes && verRes.error) return { resultCode: -717, valid: false };
|
|
2456
|
+
if (verRes.result !== true) return { resultCode: -719, valid: false };
|
|
2457
|
+
return { resultCode: 0, valid: true };
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
/**
|
|
2461
|
+
* The sendCoins function posts a send-coin transaction to the blockchain. The chainId used for signing should be provided in the initialize() function.
|
|
2462
|
+
* Since the gas fee for sending coins is fixed at 1000 coins, there is no option to set the gas fee explicitly.
|
|
2463
|
+
* It may take many seconds after submitting a transaction before the transaction is returned by the getTransactionDetails function.
|
|
2464
|
+
* Transactions are usually committed in less than 30 seconds.
|
|
2465
|
+
*
|
|
2466
|
+
* @deprecated Use signRawTransaction and postTransaction instead.
|
|
2467
|
+
* @async
|
|
2468
|
+
* @function sendCoins
|
|
2469
|
+
* @param {Wallet} wallet - A Wallet object from which the transaction has to be sent. The address corresponding to the Wallet should have enough coins to cover gas fees as well. A minimum of 1000 coins (1000000000000000000000 wei) are required for gas fees.
|
|
2470
|
+
* @param {string} toAddress - The address to which the coins should be sent.
|
|
2471
|
+
* @param {string} coins - The string representing the number of coins (in ether) to send. To convert between ethers and wei, see https://docs.ethers.org/v4/api-utils.html#ether-strings-and-wei
|
|
2472
|
+
* @param {number} nonce - The nonce of the account retrieved by invoking the getAccountDetails function. You have to carefully manage state of the nonce to avoid sending the coins multiple times, such as when retrying sendCoins after a network error.
|
|
2473
|
+
* @return {Promise<SendResult>} Returns a promise of type SendResult.
|
|
2474
|
+
*/
|
|
2475
|
+
async function sendCoins(wallet, toAddress, coins, nonce) {
|
|
2476
|
+
if (isInitialized === false) {
|
|
2477
|
+
return -1000;
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
if (wallet == null || toAddress == null || coins == null || nonce == null) {
|
|
2481
|
+
return new SendResult(-1, null, null, null);
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
if (isAddressValid(toAddress) === false) {
|
|
2485
|
+
return new SendResult(-2, null, null, null);
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
if (verifyWallet(wallet) === false) {
|
|
2489
|
+
return new SendResult(-3, null, null, null);
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
if (isLargeNumber(coins) === false) {
|
|
2493
|
+
return new SendResult(-4, null, null, null);
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
let tempNonce = parseInt(nonce);
|
|
2497
|
+
if (Number.isInteger(tempNonce) === false) {
|
|
2498
|
+
return new SendResult(-5, null, null, null);
|
|
2499
|
+
}
|
|
2500
|
+
nonce = tempNonce;
|
|
2501
|
+
if (nonce < 0) {
|
|
2502
|
+
return new SendResult(-6, null, null, null);
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
let accountDetailsResult = await getAccountDetails(wallet.address);
|
|
2506
|
+
if (accountDetailsResult === null) {
|
|
2507
|
+
return new SendResult(-7, null, null, null);
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
if (accountDetailsResult.resultCode !== 0) {
|
|
2511
|
+
return new SendResult(-7, null, null, null);
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
if (accountDetailsResult.accountDetails.nonce !== nonce) {
|
|
2515
|
+
return new SendResult(-8, null, null, null);
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
const contractData = null;
|
|
2519
|
+
|
|
2520
|
+
var txSigningHash = transactionGetSigningHash(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData);
|
|
2521
|
+
if (txSigningHash == null) {
|
|
2522
|
+
return new SendResult(-9, null, null, null);
|
|
2523
|
+
}
|
|
2524
|
+
const txSigningHashU8 = toUint8Array(txSigningHash);
|
|
2525
|
+
const hybridedsNs = circl && circl.hybrideds;
|
|
2526
|
+
if (!hybridedsNs) {
|
|
2527
|
+
return new SendResult(-10, null, null, null);
|
|
2528
|
+
}
|
|
2529
|
+
const sigRes = hybridedsNs.signCompact(toUint8Array(wallet.privateKey), txSigningHashU8);
|
|
2530
|
+
if (sigRes && sigRes.error) {
|
|
2531
|
+
return new SendResult(-10, null, null, null);
|
|
2532
|
+
}
|
|
2533
|
+
const verRes = hybridedsNs.verifyCompact(toUint8Array(wallet.publicKey), txSigningHashU8, sigRes.result);
|
|
2534
|
+
if (verRes && verRes.error) {
|
|
2535
|
+
return new SendResult(-10, null, null, null);
|
|
2536
|
+
}
|
|
2537
|
+
if (verRes.result !== true) {
|
|
2538
|
+
return new SendResult(-10, null, null, null);
|
|
2539
|
+
}
|
|
2540
|
+
const quantumSig = sigRes.result instanceof Uint8Array ? Array.from(sigRes.result) : sigRes.result;
|
|
2541
|
+
|
|
2542
|
+
var txHashHex = transactionGetTransactionHash(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData, wallet.publicKey, quantumSig);
|
|
2543
|
+
if (txHashHex == null) {
|
|
2544
|
+
return new SendResult(-11, null, null, null);
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
var txnData = transactionGetData(wallet.address, nonce, toAddress, coins, DEFAULT_GAS, config.chainId, contractData, wallet.publicKey, quantumSig);
|
|
2548
|
+
if (txnData == null) {
|
|
2549
|
+
return new SendResult(-12, null, null, null);
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
let sendResult = await postTransaction(txnData);
|
|
2553
|
+
sendResult.txnHash = txHashHex;
|
|
2554
|
+
|
|
2555
|
+
return sendResult;
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
/**
|
|
2559
|
+
* The publicKeyFromSignature extracts the public key from a signature.
|
|
2560
|
+
*
|
|
2561
|
+
* @function publicKeyFromSignature
|
|
2562
|
+
* @param {number[]} digest - An array of bytes containing the digestHash. Should be of length 32.
|
|
2563
|
+
* @param {number[]} signature - An array of bytes containing the signature.
|
|
2564
|
+
* @return {string} - Returns the public key as a hex string. Returns null if the operation failed.
|
|
2565
|
+
*/
|
|
2566
|
+
function publicKeyFromSignature(digest, signature) {
|
|
2567
|
+
if (isInitialized === false) {
|
|
2568
|
+
return -1000;
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
if (digest === undefined || digest === null || digest.length === undefined || digest.length === null || digest.length !== 32) {
|
|
2572
|
+
return null;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
if (signature === undefined || signature === null || signature.length === undefined || signature.length === null) {
|
|
2576
|
+
return null;
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
let publicKeyHex = PublicKeyFromSignature(digest, signature);
|
|
2580
|
+
|
|
2581
|
+
return publicKeyHex;
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
/**
|
|
2585
|
+
* The publicKeyFromPrivateKey extracts the public key from a private key.
|
|
2586
|
+
*
|
|
2587
|
+
* @function publicKeyFromPrivateKey
|
|
2588
|
+
* @param {number[]} privateKey - An array of bytes containing the privateKey.
|
|
2589
|
+
* @return {string} - Returns the public key as a hex string. Returns null if the operation failed.
|
|
2590
|
+
*/
|
|
2591
|
+
function publicKeyFromPrivateKey(privateKey) {
|
|
2592
|
+
if (isInitialized === false) {
|
|
2593
|
+
return -1000;
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
if (privateKey === undefined || privateKey === null || privateKey.length === undefined || privateKey.length === null) {
|
|
2597
|
+
return null;
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
let publicKeyHex = PublicKeyFromPrivateKey(privateKey);
|
|
2601
|
+
|
|
2602
|
+
return publicKeyHex;
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2605
|
+
/**
|
|
2606
|
+
* The addressFromPublicKey returns the address corresponding to the public key.
|
|
2607
|
+
*
|
|
2608
|
+
* @function addressFromPublicKey
|
|
2609
|
+
* @param {number[]} publicKey - An array of bytes containing the public key.
|
|
2610
|
+
* @return {string} - Returns the address corresponding to the public key as a hex string. Returns null if the operation failed.
|
|
2611
|
+
*/
|
|
2612
|
+
function addressFromPublicKey(publicKey) {
|
|
2613
|
+
if (isInitialized === false) {
|
|
2614
|
+
return -1000;
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
if (publicKey === undefined || publicKey === null || publicKey.length === undefined || publicKey.length === null) {
|
|
2618
|
+
return null;
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
return PublicKeyToAddress(publicKey);
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2624
|
+
/**
|
|
2625
|
+
* The combinePublicKeySignature combines the public key and signature.
|
|
2626
|
+
*
|
|
2627
|
+
* @function combinePublicKeySignature
|
|
2628
|
+
* @param {number[]} publicKey - An array of bytes containing the public key.
|
|
2629
|
+
* @param {number[]} signature - An array of bytes containing the signature.
|
|
2630
|
+
* @return {string} - Returns a hex string corresponding to combined signature. Returns null if the operation failed.
|
|
2631
|
+
*/
|
|
2632
|
+
function combinePublicKeySignature(publicKey, signature) {
|
|
2633
|
+
if (isInitialized === false) {
|
|
2634
|
+
return -1000;
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
if (publicKey === undefined || publicKey === null || publicKey.length === undefined || publicKey.length === null) {
|
|
2638
|
+
return null;
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2641
|
+
if (signature === undefined || signature === null || signature.length === undefined || signature.length === null) {
|
|
2642
|
+
return null;
|
|
2643
|
+
}
|
|
2644
|
+
|
|
2645
|
+
return CombinePublicKeySignature(publicKey, signature);
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2648
|
+
/**
|
|
2649
|
+
* The packMethodData function packs a Solidity method call with the given ABI, method name, and arguments.
|
|
2650
|
+
* It returns the transaction data as a hex string that can be included in a transaction.
|
|
2651
|
+
*
|
|
2652
|
+
* @function packMethodData
|
|
2653
|
+
* @param {string} abiJSON - The Solidity ABI file content as a JSON string
|
|
2654
|
+
* @param {string} methodName - The name of the method to call
|
|
2655
|
+
* @param {...*} args - The parameters to pass to the method (variable arguments)
|
|
2656
|
+
* @return {PackUnpackResult} - Returns a PackUnpackResult object containing the error (if any) and the packed transaction data as a hex string.
|
|
2657
|
+
*/
|
|
2658
|
+
function packMethodData(abiJSON, methodName, ...args) {
|
|
2659
|
+
if (isInitialized === false) {
|
|
2660
|
+
return new PackUnpackResult('SDK not initialized. Call initialize() first.', '');
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
if (abiJSON === undefined || abiJSON === null || typeof abiJSON !== 'string') {
|
|
2664
|
+
return new PackUnpackResult('Invalid abiJSON parameter. Expected a string.', '');
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2667
|
+
if (methodName === undefined || methodName === null || typeof methodName !== 'string') {
|
|
2668
|
+
return new PackUnpackResult('Invalid methodName parameter. Expected a string.', '');
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
try {
|
|
2672
|
+
// Call WASM PackMethodData function
|
|
2673
|
+
// The WASM function expects: (abiJSON, methodName, ...args)
|
|
2674
|
+
const result = PackMethodData(abiJSON, methodName, ...args);
|
|
2675
|
+
|
|
2676
|
+
// Check if WASM returned an Error object
|
|
2677
|
+
if (result instanceof Error) {
|
|
2678
|
+
return new PackUnpackResult(result.message || 'Unknown error from WASM', '');
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2681
|
+
if (result === null || result === undefined) {
|
|
2682
|
+
return new PackUnpackResult('PackMethodData returned null or undefined', '');
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
// The WASM returns a string where each character is a byte
|
|
2686
|
+
// Convert to hex string
|
|
2687
|
+
let hex = '0x';
|
|
2688
|
+
for (let i = 0; i < result.length; i++) {
|
|
2689
|
+
const byte = result.charCodeAt(i);
|
|
2690
|
+
const hexByte = byte.toString(16);
|
|
2691
|
+
hex += hexByte.length === 1 ? '0' + hexByte : hexByte;
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
return new PackUnpackResult('', hex);
|
|
2695
|
+
} catch (error) {
|
|
2696
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2697
|
+
return new PackUnpackResult(errorMessage, '');
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
/**
|
|
2702
|
+
* The unpackMethodData function unpacks the return values of a Solidity method call.
|
|
2703
|
+
* It returns the unpacked values as a JavaScript array or object.
|
|
2704
|
+
*
|
|
2705
|
+
* @function unpackMethodData
|
|
2706
|
+
* @param {string} abiJSON - The Solidity ABI file content as a JSON string
|
|
2707
|
+
* @param {string} methodName - The name of the method whose return values to unpack
|
|
2708
|
+
* @param {string} hexData - The hex-encoded return data (with or without 0x prefix)
|
|
2709
|
+
* @return {PackUnpackResult} - Returns a PackUnpackResult object containing the error (if any) and the unpacked return values as a JSON string.
|
|
2710
|
+
*/
|
|
2711
|
+
function unpackMethodData(abiJSON, methodName, hexData) {
|
|
2712
|
+
if (isInitialized === false) {
|
|
2713
|
+
return new PackUnpackResult('SDK not initialized. Call initialize() first.', '');
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
if (abiJSON === undefined || abiJSON === null || typeof abiJSON !== 'string') {
|
|
2717
|
+
return new PackUnpackResult('Invalid abiJSON parameter. Expected a string.', '');
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2720
|
+
if (methodName === undefined || methodName === null || typeof methodName !== 'string') {
|
|
2721
|
+
return new PackUnpackResult('Invalid methodName parameter. Expected a string.', '');
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2724
|
+
if (hexData === undefined || hexData === null || typeof hexData !== 'string') {
|
|
2725
|
+
return new PackUnpackResult('Invalid hexData parameter. Expected a string.', '');
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
try {
|
|
2729
|
+
// Call WASM UnpackMethodData function
|
|
2730
|
+
const result = UnpackMethodData(abiJSON, methodName, hexData);
|
|
2731
|
+
|
|
2732
|
+
// Check if WASM returned an Error object
|
|
2733
|
+
if (result instanceof Error) {
|
|
2734
|
+
return new PackUnpackResult(result.message || 'Unknown error from WASM', '');
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
if (result === null || result === undefined) {
|
|
2738
|
+
return new PackUnpackResult('UnpackMethodData returned null or undefined', '');
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
// Return the JSON string result directly
|
|
2742
|
+
return new PackUnpackResult('', result);
|
|
2743
|
+
} catch (error) {
|
|
2744
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2745
|
+
return new PackUnpackResult(errorMessage, '');
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
/**
|
|
2750
|
+
* The packCreateContractData function packs constructor data for contract creation.
|
|
2751
|
+
* It combines the contract bytecode with the ABI-encoded constructor parameters.
|
|
2752
|
+
* This matches the Go pattern: Pack("", params...) and append(bytecode, input...)
|
|
2753
|
+
*
|
|
2754
|
+
* @function packCreateContractData
|
|
2755
|
+
* @param {string} abiJSON - The Solidity ABI file content as a JSON string
|
|
2756
|
+
* @param {string} bytecode - The contract bytecode as a hex string (with or without 0x prefix)
|
|
2757
|
+
* @param {...*} args - The constructor parameters (variable arguments, can be 0 or more)
|
|
2758
|
+
* @return {PackUnpackResult} - Returns a PackUnpackResult object containing the error (if any) and the packed contract creation data as a hex string.
|
|
2759
|
+
*/
|
|
2760
|
+
function packCreateContractData(abiJSON, bytecode, ...args) {
|
|
2761
|
+
if (isInitialized === false) {
|
|
2762
|
+
return new PackUnpackResult('SDK not initialized. Call initialize() first.', '');
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2765
|
+
if (abiJSON === undefined || abiJSON === null || typeof abiJSON !== 'string') {
|
|
2766
|
+
return new PackUnpackResult('Invalid abiJSON parameter. Expected a string.', '');
|
|
2767
|
+
}
|
|
2768
|
+
|
|
2769
|
+
if (bytecode === undefined || bytecode === null || typeof bytecode !== 'string') {
|
|
2770
|
+
return new PackUnpackResult('Invalid bytecode parameter. Expected a string.', '');
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2773
|
+
try {
|
|
2774
|
+
// Call WASM PackCreateContractData function
|
|
2775
|
+
// The WASM function expects: (abiJSON, bytecode, ...args)
|
|
2776
|
+
const result = PackCreateContractData(abiJSON, bytecode, ...args);
|
|
2777
|
+
|
|
2778
|
+
// Check if WASM returned an Error object
|
|
2779
|
+
if (result instanceof Error) {
|
|
2780
|
+
return new PackUnpackResult(result.message || 'Unknown error from WASM', '');
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
if (result === null || result === undefined) {
|
|
2784
|
+
return new PackUnpackResult('PackCreateContractData returned null or undefined', '');
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
// The WASM returns a string where each character is a byte
|
|
2788
|
+
// Convert to hex string
|
|
2789
|
+
let hex = '0x';
|
|
2790
|
+
for (let i = 0; i < result.length; i++) {
|
|
2791
|
+
const byte = result.charCodeAt(i);
|
|
2792
|
+
const hexByte = byte.toString(16);
|
|
2793
|
+
hex += hexByte.length === 1 ? '0' + hexByte : hexByte;
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2796
|
+
return new PackUnpackResult('', hex);
|
|
2797
|
+
} catch (error) {
|
|
2798
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2799
|
+
return new PackUnpackResult(errorMessage, '');
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
/**
|
|
2804
|
+
* The encodeEventLog function encodes event parameters into topics and data according to the ABI specification.
|
|
2805
|
+
* It returns the topics array and data hex string that can be used to create event logs.
|
|
2806
|
+
*
|
|
2807
|
+
* @function encodeEventLog
|
|
2808
|
+
* @param {string} abiJSON - The Solidity ABI file content as a JSON string
|
|
2809
|
+
* @param {string} eventName - The name of the event to encode
|
|
2810
|
+
* @param {...*} args - The event parameter values (variable arguments)
|
|
2811
|
+
* @return {EventLogEncodeResult} - Returns an EventLogEncodeResult object containing the error (if any) and the encoded event log with topics and data.
|
|
2812
|
+
*/
|
|
2813
|
+
function encodeEventLog(abiJSON, eventName, ...args) {
|
|
2814
|
+
if (isInitialized === false) {
|
|
2815
|
+
return new EventLogEncodeResult('SDK not initialized. Call initialize() first.', null);
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
if (abiJSON === undefined || abiJSON === null || typeof abiJSON !== 'string') {
|
|
2819
|
+
return new EventLogEncodeResult('Invalid abiJSON parameter. Expected a string.', null);
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
if (eventName === undefined || eventName === null || typeof eventName !== 'string') {
|
|
2823
|
+
return new EventLogEncodeResult('Invalid eventName parameter. Expected a string.', null);
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
try {
|
|
2827
|
+
// Call WASM EncodeEventLog function
|
|
2828
|
+
// The WASM function expects: (abiJSON, eventName, ...args)
|
|
2829
|
+
const result = EncodeEventLog(abiJSON, eventName, ...args);
|
|
2830
|
+
|
|
2831
|
+
// Check if WASM returned an Error object
|
|
2832
|
+
if (result instanceof Error) {
|
|
2833
|
+
return new EventLogEncodeResult(result.message || 'Unknown error from WASM', null);
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2836
|
+
if (result === null || result === undefined) {
|
|
2837
|
+
return new EventLogEncodeResult('EncodeEventLog returned null or undefined', null);
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
// The WASM returns a JavaScript object with topics (array) and data (hex string)
|
|
2841
|
+
// Extract topics array and data
|
|
2842
|
+
const topics = result.topics || [];
|
|
2843
|
+
const data = result.data || '0x';
|
|
2844
|
+
|
|
2845
|
+
// Ensure topics is an array and data is a string
|
|
2846
|
+
if (!Array.isArray(topics)) {
|
|
2847
|
+
return new EventLogEncodeResult('EncodeEventLog returned invalid topics (not an array)', null);
|
|
2848
|
+
}
|
|
2849
|
+
|
|
2850
|
+
if (typeof data !== 'string') {
|
|
2851
|
+
return new EventLogEncodeResult('EncodeEventLog returned invalid data (not a string)', null);
|
|
2852
|
+
}
|
|
2853
|
+
|
|
2854
|
+
return new EventLogEncodeResult('', { topics, data });
|
|
2855
|
+
} catch (error) {
|
|
2856
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2857
|
+
return new EventLogEncodeResult(errorMessage, null);
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
/**
|
|
2862
|
+
* The decodeEventLog function decodes event log topics and data back into event parameters.
|
|
2863
|
+
* It returns the decoded values as a JavaScript object.
|
|
2864
|
+
*
|
|
2865
|
+
* @function decodeEventLog
|
|
2866
|
+
* @param {string} abiJSON - The Solidity ABI file content as a JSON string
|
|
2867
|
+
* @param {string} eventName - The name of the event to decode
|
|
2868
|
+
* @param {string[]} topics - Array of topic hex strings (with or without 0x prefix)
|
|
2869
|
+
* @param {string} data - Hex-encoded data string (with or without 0x prefix)
|
|
2870
|
+
* @return {PackUnpackResult} - Returns a PackUnpackResult object containing the error (if any) and the decoded event parameters as a JSON string.
|
|
2871
|
+
*/
|
|
2872
|
+
function decodeEventLog(abiJSON, eventName, topics, data) {
|
|
2873
|
+
if (isInitialized === false) {
|
|
2874
|
+
return new PackUnpackResult('SDK not initialized. Call initialize() first.', '');
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2877
|
+
if (abiJSON === undefined || abiJSON === null || typeof abiJSON !== 'string') {
|
|
2878
|
+
return new PackUnpackResult('Invalid abiJSON parameter. Expected a string.', '');
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
if (eventName === undefined || eventName === null || typeof eventName !== 'string') {
|
|
2882
|
+
return new PackUnpackResult('Invalid eventName parameter. Expected a string.', '');
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
if (topics === undefined || topics === null || !Array.isArray(topics)) {
|
|
2886
|
+
return new PackUnpackResult('Invalid topics parameter. Expected an array of strings.', '');
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
if (data === undefined || data === null || typeof data !== 'string') {
|
|
2890
|
+
return new PackUnpackResult('Invalid data parameter. Expected a string.', '');
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2893
|
+
try {
|
|
2894
|
+
// Call WASM DecodeEventLog function
|
|
2895
|
+
const result = DecodeEventLog(abiJSON, eventName, topics, data);
|
|
2896
|
+
|
|
2897
|
+
// Check if WASM returned an Error object
|
|
2898
|
+
if (result instanceof Error) {
|
|
2899
|
+
return new PackUnpackResult(result.message || 'Unknown error from WASM', '');
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
if (result === null || result === undefined) {
|
|
2903
|
+
return new PackUnpackResult('DecodeEventLog returned null or undefined', '');
|
|
2904
|
+
}
|
|
2905
|
+
|
|
2906
|
+
// The WASM returns a JSON string
|
|
2907
|
+
if (typeof result !== 'string') {
|
|
2908
|
+
return new PackUnpackResult('DecodeEventLog returned invalid result (not a string)', '');
|
|
2909
|
+
}
|
|
2910
|
+
|
|
2911
|
+
return new PackUnpackResult('', result);
|
|
2912
|
+
} catch (error) {
|
|
2913
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2914
|
+
return new PackUnpackResult(errorMessage, '');
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
|
|
2918
|
+
/**
|
|
2919
|
+
* The encodeRlp function encodes a JavaScript value to RLP (Recursive Length Prefix) format.
|
|
2920
|
+
* Supports: strings, numbers, booleans, arrays, objects (maps), and hex-encoded bytes.
|
|
2921
|
+
* Returns a hex-encoded string of the RLP-encoded data.
|
|
2922
|
+
*
|
|
2923
|
+
* @function encodeRlp
|
|
2924
|
+
* @param {*} value - The value to encode (can be string, number, boolean, array, object, etc.)
|
|
2925
|
+
* @return {PackUnpackResult} - Returns a PackUnpackResult object containing the error (if any) and the RLP-encoded data as a hex string.
|
|
2926
|
+
*/
|
|
2927
|
+
function encodeRlp(value) {
|
|
2928
|
+
if (isInitialized === false) {
|
|
2929
|
+
return new PackUnpackResult('SDK not initialized. Call initialize() first.', '');
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
// Note: null and undefined are valid inputs and will be encoded as empty bytes
|
|
2933
|
+
|
|
2934
|
+
try {
|
|
2935
|
+
// Call WASM EncodeRlp function
|
|
2936
|
+
const result = EncodeRlp(value);
|
|
2937
|
+
|
|
2938
|
+
// Check if WASM returned an Error object
|
|
2939
|
+
if (result instanceof Error) {
|
|
2940
|
+
return new PackUnpackResult(result.message || 'Unknown error from WASM', '');
|
|
2941
|
+
}
|
|
2942
|
+
|
|
2943
|
+
if (result === null || result === undefined) {
|
|
2944
|
+
return new PackUnpackResult('EncodeRlp returned null or undefined', '');
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2947
|
+
// The WASM returns a hex string
|
|
2948
|
+
if (typeof result !== 'string') {
|
|
2949
|
+
return new PackUnpackResult('EncodeRlp returned invalid result (not a string)', '');
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
return new PackUnpackResult('', result);
|
|
2953
|
+
} catch (error) {
|
|
2954
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2955
|
+
return new PackUnpackResult(errorMessage, '');
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2959
|
+
/**
|
|
2960
|
+
* The decodeRlp function decodes RLP-encoded data back to a JavaScript-compatible value.
|
|
2961
|
+
* Takes a hex-encoded string and returns a JSON string representation of the decoded value.
|
|
2962
|
+
*
|
|
2963
|
+
* @function decodeRlp
|
|
2964
|
+
* @param {string} data - The hex-encoded RLP data (with or without 0x prefix)
|
|
2965
|
+
* @return {PackUnpackResult} - Returns a PackUnpackResult object containing the error (if any) and the decoded value as a JSON string.
|
|
2966
|
+
*/
|
|
2967
|
+
function decodeRlp(data) {
|
|
2968
|
+
if (isInitialized === false) {
|
|
2969
|
+
return new PackUnpackResult('SDK not initialized. Call initialize() first.', '');
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
if (data === undefined || data === null || typeof data !== 'string') {
|
|
2973
|
+
return new PackUnpackResult('Invalid data parameter. Expected a string.', '');
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2976
|
+
try {
|
|
2977
|
+
// Call WASM DecodeRlp function
|
|
2978
|
+
const result = DecodeRlp(data);
|
|
2979
|
+
|
|
2980
|
+
// Check if WASM returned an Error object
|
|
2981
|
+
if (result instanceof Error) {
|
|
2982
|
+
return new PackUnpackResult(result.message || 'Unknown error from WASM', '');
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
if (result === null || result === undefined) {
|
|
2986
|
+
return new PackUnpackResult('DecodeRlp returned null or undefined', '');
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2989
|
+
// The WASM returns a JSON string
|
|
2990
|
+
if (typeof result !== 'string') {
|
|
2991
|
+
return new PackUnpackResult('DecodeRlp returned invalid result (not a string)', '');
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2994
|
+
return new PackUnpackResult('', result);
|
|
2995
|
+
} catch (error) {
|
|
2996
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2997
|
+
return new PackUnpackResult(errorMessage, '');
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
/**
|
|
3002
|
+
* The createAddress function calculates the contract address that will be created by a transaction.
|
|
3003
|
+
* This uses the CREATE opcode address calculation: keccak256(RLP(sender, nonce))
|
|
3004
|
+
*
|
|
3005
|
+
* @function createAddress
|
|
3006
|
+
* @param {string} address - The address of the account that will create the contract (hex string with 0x prefix)
|
|
3007
|
+
* @param {number} nonce - The nonce of the account at the time of contract creation
|
|
3008
|
+
* @return {string|null} - Returns the contract address as a hex string, or null if an error occurred.
|
|
3009
|
+
*/
|
|
3010
|
+
function createAddress(address, nonce) {
|
|
3011
|
+
if (isInitialized === false) {
|
|
3012
|
+
return null;
|
|
3013
|
+
}
|
|
3014
|
+
|
|
3015
|
+
if (address === undefined || address === null || typeof address !== 'string') {
|
|
3016
|
+
return null;
|
|
3017
|
+
}
|
|
3018
|
+
|
|
3019
|
+
if (nonce === undefined || nonce === null || typeof nonce !== 'number') {
|
|
3020
|
+
return null;
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
try {
|
|
3024
|
+
// Call WASM CreateAddress function
|
|
3025
|
+
// The WASM function expects: (address, nonce as string)
|
|
3026
|
+
const result = CreateAddress(address, nonce.toString());
|
|
3027
|
+
|
|
3028
|
+
// Check if WASM returned an Error object
|
|
3029
|
+
if (result instanceof Error) {
|
|
3030
|
+
return null;
|
|
3031
|
+
}
|
|
3032
|
+
|
|
3033
|
+
if (result === null || result === undefined) {
|
|
3034
|
+
return null;
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
// Return the address string directly
|
|
3038
|
+
return result;
|
|
3039
|
+
} catch (error) {
|
|
3040
|
+
return null;
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
|
|
3044
|
+
/**
|
|
3045
|
+
* The createAddress2 function calculates the contract address using the CREATE2 opcode.
|
|
3046
|
+
* This allows deterministic contract address calculation: keccak256(0xff || sender || salt || keccak256(init_code))
|
|
3047
|
+
*
|
|
3048
|
+
* @function createAddress2
|
|
3049
|
+
* @param {string} address - The address of the account that will create the contract (hex string with 0x prefix)
|
|
3050
|
+
* @param {string} salt - A 32-byte salt value as a hex string (with 0x prefix)
|
|
3051
|
+
* @param {string} initHash - The keccak256 hash of the contract initialization code as a hex string (with 0x prefix)
|
|
3052
|
+
* @return {string|null} - Returns the contract address as a hex string, or null if an error occurred.
|
|
3053
|
+
*/
|
|
3054
|
+
function createAddress2(address, salt, initHash) {
|
|
3055
|
+
if (isInitialized === false) {
|
|
3056
|
+
return null;
|
|
3057
|
+
}
|
|
3058
|
+
|
|
3059
|
+
if (address === undefined || address === null || typeof address !== 'string') {
|
|
3060
|
+
return null;
|
|
3061
|
+
}
|
|
3062
|
+
|
|
3063
|
+
if (salt === undefined || salt === null || typeof salt !== 'string') {
|
|
3064
|
+
return null;
|
|
3065
|
+
}
|
|
3066
|
+
|
|
3067
|
+
if (initHash === undefined || initHash === null || typeof initHash !== 'string') {
|
|
3068
|
+
return null;
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
try {
|
|
3072
|
+
// Call WASM CreateAddress2 function
|
|
3073
|
+
// The WASM function expects: (address, salt, initHash)
|
|
3074
|
+
const result = CreateAddress2(address, salt, initHash);
|
|
3075
|
+
|
|
3076
|
+
// Check if WASM returned an Error object
|
|
3077
|
+
if (result instanceof Error) {
|
|
3078
|
+
return null;
|
|
3079
|
+
}
|
|
3080
|
+
|
|
3081
|
+
if (result === null || result === undefined) {
|
|
3082
|
+
return null;
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3085
|
+
// Return the address string directly
|
|
3086
|
+
return result;
|
|
3087
|
+
} catch (error) {
|
|
3088
|
+
return null;
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
|
|
3092
|
+
module.exports = {
|
|
3093
|
+
initialize,
|
|
3094
|
+
serializeWallet,
|
|
3095
|
+
deserializeWallet,
|
|
3096
|
+
serializeEncryptedWallet,
|
|
3097
|
+
serializeSeedAsEncryptedWallet,
|
|
3098
|
+
deserializeEncryptedWallet,
|
|
3099
|
+
verifyWallet,
|
|
3100
|
+
newWallet,
|
|
3101
|
+
sendCoins,
|
|
3102
|
+
getAccountDetails,
|
|
3103
|
+
getTransactionDetails,
|
|
3104
|
+
isAddressValid,
|
|
3105
|
+
getLatestBlockDetails,
|
|
3106
|
+
signSendCoinTransaction,
|
|
3107
|
+
listAccountTransactions,
|
|
3108
|
+
postTransaction,
|
|
3109
|
+
Config,
|
|
3110
|
+
Wallet,
|
|
3111
|
+
BlockDetails,
|
|
3112
|
+
LatestBlockDetailsResult,
|
|
3113
|
+
AccountDetails,
|
|
3114
|
+
AccountDetailsResult,
|
|
3115
|
+
SendResult,
|
|
3116
|
+
TransactionReceipt,
|
|
3117
|
+
TransactionDetails,
|
|
3118
|
+
TransactionDetailsResult,
|
|
3119
|
+
AccountTransactionsResult,
|
|
3120
|
+
ListAccountTransactionsResponse,
|
|
3121
|
+
AccountTransactionCompact,
|
|
3122
|
+
newWalletSeedWords,
|
|
3123
|
+
openWalletFromSeed,
|
|
3124
|
+
openWalletFromSeedWords,
|
|
3125
|
+
publicKeyFromSignature,
|
|
3126
|
+
publicKeyFromPrivateKey,
|
|
3127
|
+
addressFromPublicKey,
|
|
3128
|
+
combinePublicKeySignature,
|
|
3129
|
+
TransactionSigningRequest,
|
|
3130
|
+
signRawTransaction,
|
|
3131
|
+
sign,
|
|
3132
|
+
verify,
|
|
3133
|
+
packMethodData,
|
|
3134
|
+
unpackMethodData,
|
|
3135
|
+
packCreateContractData,
|
|
3136
|
+
encodeEventLog,
|
|
3137
|
+
decodeEventLog,
|
|
3138
|
+
encodeRlp,
|
|
3139
|
+
decodeRlp,
|
|
3140
|
+
createAddress,
|
|
3141
|
+
createAddress2,
|
|
3142
|
+
PackUnpackResult,
|
|
3143
|
+
EventLogEncodeResult
|
|
3144
|
+
};
|