@alephium/web3 0.30.2 → 0.31.0
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/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/src/api/api-alephium.d.ts +39 -25
- package/dist/src/api/api-alephium.js +49 -34
- package/dist/src/api/node-provider.js +1 -2
- package/dist/src/contract/contract.d.ts +1 -0
- package/dist/src/contract/contract.js +42 -8
- package/dist/src/utils/address.d.ts +20 -1
- package/dist/src/utils/address.js +168 -14
- package/dist/src/utils/error.d.ts +15 -0
- package/dist/src/utils/error.js +66 -0
- package/dist/src/utils/utils.d.ts +0 -19
- package/dist/src/utils/utils.js +1 -152
- package/package.json +2 -2
- package/src/api/api-alephium.ts +64 -44
- package/src/api/node-provider.ts +1 -2
- package/src/contract/contract.ts +62 -10
- package/src/utils/address.ts +167 -12
- package/src/utils/error.ts +77 -0
- package/src/utils/utils.ts +0 -155
package/dist/src/utils/utils.js
CHANGED
|
@@ -20,14 +20,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
20
20
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.assertType = exports.isDevnet = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.
|
|
23
|
+
exports.assertType = exports.isDevnet = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.binToHex = exports.hexToBinUnsafe = exports.toNonNegativeBigInt = exports.isHexString = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = exports.networkIds = void 0;
|
|
24
24
|
const elliptic_1 = require("elliptic");
|
|
25
25
|
const bn_js_1 = __importDefault(require("bn.js"));
|
|
26
|
-
const blakejs_1 = __importDefault(require("blakejs"));
|
|
27
|
-
const bs58_1 = __importDefault(require("./bs58"));
|
|
28
26
|
const buffer_1 = require("buffer/");
|
|
29
27
|
const constants_1 = require("../constants");
|
|
30
|
-
const djb2_1 = __importDefault(require("./djb2"));
|
|
31
28
|
exports.networkIds = ['mainnet', 'testnet', 'devnet'];
|
|
32
29
|
const ec = new elliptic_1.ec('secp256k1');
|
|
33
30
|
function encodeSignature(signature) {
|
|
@@ -60,14 +57,6 @@ function signatureDecode(ec, signature) {
|
|
|
60
57
|
}
|
|
61
58
|
}
|
|
62
59
|
exports.signatureDecode = signatureDecode;
|
|
63
|
-
function xorByte(intValue) {
|
|
64
|
-
const byte0 = (intValue >> 24) & 0xff;
|
|
65
|
-
const byte1 = (intValue >> 16) & 0xff;
|
|
66
|
-
const byte2 = (intValue >> 8) & 0xff;
|
|
67
|
-
const byte3 = intValue & 0xff;
|
|
68
|
-
return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff;
|
|
69
|
-
}
|
|
70
|
-
exports.xorByte = xorByte;
|
|
71
60
|
function isHexString(input) {
|
|
72
61
|
return input.length % 2 === 0 && /^[0-9a-fA-F]*$/.test(input);
|
|
73
62
|
}
|
|
@@ -82,80 +71,6 @@ function toNonNegativeBigInt(input) {
|
|
|
82
71
|
}
|
|
83
72
|
}
|
|
84
73
|
exports.toNonNegativeBigInt = toNonNegativeBigInt;
|
|
85
|
-
var AddressType;
|
|
86
|
-
(function (AddressType) {
|
|
87
|
-
AddressType[AddressType["P2PKH"] = 0] = "P2PKH";
|
|
88
|
-
AddressType[AddressType["P2MPKH"] = 1] = "P2MPKH";
|
|
89
|
-
AddressType[AddressType["P2SH"] = 2] = "P2SH";
|
|
90
|
-
AddressType[AddressType["P2C"] = 3] = "P2C";
|
|
91
|
-
})(AddressType = exports.AddressType || (exports.AddressType = {}));
|
|
92
|
-
function groupOfAddress(address) {
|
|
93
|
-
const decoded = bs58_1.default.decode(address);
|
|
94
|
-
if (decoded.length == 0)
|
|
95
|
-
throw new Error('Address string is empty');
|
|
96
|
-
const addressType = decoded[0];
|
|
97
|
-
const addressBody = decoded.slice(1);
|
|
98
|
-
if (addressType == AddressType.P2PKH) {
|
|
99
|
-
return groupOfP2pkhAddress(addressBody);
|
|
100
|
-
}
|
|
101
|
-
else if (addressType == AddressType.P2MPKH) {
|
|
102
|
-
return groupOfP2mpkhAddress(addressBody);
|
|
103
|
-
}
|
|
104
|
-
else if (addressType == AddressType.P2SH) {
|
|
105
|
-
return groupOfP2shAddress(addressBody);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
// Contract Address
|
|
109
|
-
const id = contractIdFromAddress(address);
|
|
110
|
-
return id[`${id.length - 1}`];
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
exports.groupOfAddress = groupOfAddress;
|
|
114
|
-
function groupOfAddressBytes(bytes) {
|
|
115
|
-
const hint = (0, djb2_1.default)(bytes) | 1;
|
|
116
|
-
const hash = xorByte(hint);
|
|
117
|
-
const group = hash % constants_1.TOTAL_NUMBER_OF_GROUPS;
|
|
118
|
-
return group;
|
|
119
|
-
}
|
|
120
|
-
// Pay to public key hash address
|
|
121
|
-
function groupOfP2pkhAddress(address) {
|
|
122
|
-
if (address.length != 32) {
|
|
123
|
-
throw new Error(`Invalid p2pkh address length: ${address.length}`);
|
|
124
|
-
}
|
|
125
|
-
return groupOfAddressBytes(address);
|
|
126
|
-
}
|
|
127
|
-
// Pay to multiple public key hash address
|
|
128
|
-
function groupOfP2mpkhAddress(address) {
|
|
129
|
-
if ((address.length - 2) % 32 != 0) {
|
|
130
|
-
throw new Error(`Invalid p2mpkh address length: ${address.length}`);
|
|
131
|
-
}
|
|
132
|
-
return groupOfAddressBytes(address.slice(1, 33));
|
|
133
|
-
}
|
|
134
|
-
// Pay to script hash address
|
|
135
|
-
function groupOfP2shAddress(address) {
|
|
136
|
-
return groupOfAddressBytes(address);
|
|
137
|
-
}
|
|
138
|
-
function contractIdFromAddress(address) {
|
|
139
|
-
return idFromAddress(address);
|
|
140
|
-
}
|
|
141
|
-
exports.contractIdFromAddress = contractIdFromAddress;
|
|
142
|
-
function tokenIdFromAddress(address) {
|
|
143
|
-
return idFromAddress(address);
|
|
144
|
-
}
|
|
145
|
-
exports.tokenIdFromAddress = tokenIdFromAddress;
|
|
146
|
-
function idFromAddress(address) {
|
|
147
|
-
const decoded = bs58_1.default.decode(address);
|
|
148
|
-
if (decoded.length == 0)
|
|
149
|
-
throw new Error('Address string is empty');
|
|
150
|
-
const addressType = decoded[0];
|
|
151
|
-
const addressBody = decoded.slice(1);
|
|
152
|
-
if (addressType == AddressType.P2C) {
|
|
153
|
-
return addressBody;
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
throw new Error(`Invalid contract address type: ${addressType}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
74
|
function hexToBinUnsafe(hex) {
|
|
160
75
|
return buffer_1.Buffer.from(hex, 'hex');
|
|
161
76
|
}
|
|
@@ -164,72 +79,6 @@ function binToHex(bin) {
|
|
|
164
79
|
return buffer_1.Buffer.from(bin).toString('hex');
|
|
165
80
|
}
|
|
166
81
|
exports.binToHex = binToHex;
|
|
167
|
-
function groupOfPrivateKey(privateKey, keyType) {
|
|
168
|
-
return groupOfAddress(addressFromPublicKey(publicKeyFromPrivateKey(privateKey, keyType), keyType));
|
|
169
|
-
}
|
|
170
|
-
exports.groupOfPrivateKey = groupOfPrivateKey;
|
|
171
|
-
function publicKeyFromPrivateKey(privateKey, _keyType) {
|
|
172
|
-
const keyType = _keyType ?? 'default';
|
|
173
|
-
if (keyType === 'default') {
|
|
174
|
-
const key = ec.keyFromPrivate(privateKey);
|
|
175
|
-
return key.getPublic(true, 'hex');
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
return ec.g.mul(new bn_js_1.default(privateKey, 16)).encode('hex', true).slice(2);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
exports.publicKeyFromPrivateKey = publicKeyFromPrivateKey;
|
|
182
|
-
function addressFromPublicKey(publicKey, _keyType) {
|
|
183
|
-
const keyType = _keyType ?? 'default';
|
|
184
|
-
if (keyType === 'default') {
|
|
185
|
-
const addressType = buffer_1.Buffer.from([AddressType.P2PKH]);
|
|
186
|
-
const hash = buffer_1.Buffer.from(blakejs_1.default.blake2b(buffer_1.Buffer.from(publicKey, 'hex'), undefined, 32));
|
|
187
|
-
const bytes = buffer_1.Buffer.concat([addressType, hash]);
|
|
188
|
-
return bs58_1.default.encode(bytes);
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
const lockupScript = buffer_1.Buffer.from(`0101000000000458144020${publicKey}8685`, 'hex');
|
|
192
|
-
return addressFromScript(lockupScript);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
exports.addressFromPublicKey = addressFromPublicKey;
|
|
196
|
-
function addressFromScript(script) {
|
|
197
|
-
const scriptHash = blakejs_1.default.blake2b(script, undefined, 32);
|
|
198
|
-
const addressType = buffer_1.Buffer.from([AddressType.P2SH]);
|
|
199
|
-
return bs58_1.default.encode(buffer_1.Buffer.concat([addressType, scriptHash]));
|
|
200
|
-
}
|
|
201
|
-
exports.addressFromScript = addressFromScript;
|
|
202
|
-
function addressFromContractId(contractId) {
|
|
203
|
-
const addressType = buffer_1.Buffer.from([AddressType.P2C]);
|
|
204
|
-
const hash = buffer_1.Buffer.from(hexToBinUnsafe(contractId));
|
|
205
|
-
const bytes = buffer_1.Buffer.concat([addressType, hash]);
|
|
206
|
-
return bs58_1.default.encode(bytes);
|
|
207
|
-
}
|
|
208
|
-
exports.addressFromContractId = addressFromContractId;
|
|
209
|
-
function addressFromTokenId(tokenId) {
|
|
210
|
-
const contractId = tokenId; // contract ID is the same as token ID
|
|
211
|
-
return addressFromContractId(contractId);
|
|
212
|
-
}
|
|
213
|
-
exports.addressFromTokenId = addressFromTokenId;
|
|
214
|
-
function contractIdFromTx(txId, outputIndex) {
|
|
215
|
-
const txIdBin = hexToBinUnsafe(txId);
|
|
216
|
-
const data = buffer_1.Buffer.concat([txIdBin, buffer_1.Buffer.from([outputIndex])]);
|
|
217
|
-
const hash = blakejs_1.default.blake2b(data, undefined, 32);
|
|
218
|
-
return binToHex(hash);
|
|
219
|
-
}
|
|
220
|
-
exports.contractIdFromTx = contractIdFromTx;
|
|
221
|
-
function subContractId(parentContractId, pathInHex, group) {
|
|
222
|
-
if (group < 0 || group >= constants_1.TOTAL_NUMBER_OF_GROUPS) {
|
|
223
|
-
throw new Error(`Invalid group ${group}`);
|
|
224
|
-
}
|
|
225
|
-
const data = buffer_1.Buffer.concat([hexToBinUnsafe(parentContractId), hexToBinUnsafe(pathInHex)]);
|
|
226
|
-
const bytes = buffer_1.Buffer.concat([
|
|
227
|
-
blakejs_1.default.blake2b(blakejs_1.default.blake2b(data, undefined, 32), undefined, 32).slice(0, -1),
|
|
228
|
-
buffer_1.Buffer.from([group])
|
|
229
|
-
]);
|
|
230
|
-
return binToHex(bytes);
|
|
231
|
-
}
|
|
232
|
-
exports.subContractId = subContractId;
|
|
233
82
|
function blockChainIndex(blockHash) {
|
|
234
83
|
if (blockHash.length != 64) {
|
|
235
84
|
throw Error(`Invalid block hash: ${blockHash}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alephium/web3",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "A JS/TS library to interact with the Alephium platform",
|
|
5
5
|
"license": "GPL",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"author": "Alephium dev <dev@alephium.org>",
|
|
29
29
|
"config": {
|
|
30
|
-
"alephium_version": "2.8.
|
|
30
|
+
"alephium_version": "2.8.5",
|
|
31
31
|
"explorer_backend_version": "1.16.1"
|
|
32
32
|
},
|
|
33
33
|
"type": "commonjs",
|
package/src/api/api-alephium.ts
CHANGED
|
@@ -752,6 +752,11 @@ export interface Reachable {
|
|
|
752
752
|
type: string
|
|
753
753
|
}
|
|
754
754
|
|
|
755
|
+
export interface Result {
|
|
756
|
+
/** @format bigint */
|
|
757
|
+
hashrate: string
|
|
758
|
+
}
|
|
759
|
+
|
|
755
760
|
export interface RevealMnemonic {
|
|
756
761
|
password: string
|
|
757
762
|
}
|
|
@@ -842,6 +847,11 @@ export interface SweepAddressTransaction {
|
|
|
842
847
|
gasPrice: string
|
|
843
848
|
}
|
|
844
849
|
|
|
850
|
+
export interface TargetToHashrate {
|
|
851
|
+
/** @format hex-string */
|
|
852
|
+
target: string
|
|
853
|
+
}
|
|
854
|
+
|
|
845
855
|
export interface TestContract {
|
|
846
856
|
/** @format int32 */
|
|
847
857
|
group?: number
|
|
@@ -1282,7 +1292,7 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
1282
1292
|
|
|
1283
1293
|
/**
|
|
1284
1294
|
* @title Alephium API
|
|
1285
|
-
* @version 2.8.
|
|
1295
|
+
* @version 2.8.5
|
|
1286
1296
|
* @baseUrl ../
|
|
1287
1297
|
*/
|
|
1288
1298
|
export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
|
|
@@ -2460,18 +2470,10 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
|
|
2460
2470
|
* @summary Get contract state
|
|
2461
2471
|
* @request GET:/contracts/{address}/state
|
|
2462
2472
|
*/
|
|
2463
|
-
getContractsAddressState: (
|
|
2464
|
-
address: string,
|
|
2465
|
-
query: {
|
|
2466
|
-
/** @format int32 */
|
|
2467
|
-
group: number
|
|
2468
|
-
},
|
|
2469
|
-
params: RequestParams = {}
|
|
2470
|
-
) =>
|
|
2473
|
+
getContractsAddressState: (address: string, params: RequestParams = {}) =>
|
|
2471
2474
|
this.request<ContractState, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
|
|
2472
2475
|
path: `/contracts/${address}/state`,
|
|
2473
2476
|
method: 'GET',
|
|
2474
|
-
query: query,
|
|
2475
2477
|
format: 'json',
|
|
2476
2478
|
...params
|
|
2477
2479
|
}).then(convertHttpResponse),
|
|
@@ -2619,40 +2621,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
|
|
2619
2621
|
...params
|
|
2620
2622
|
}).then(convertHttpResponse)
|
|
2621
2623
|
}
|
|
2622
|
-
utils = {
|
|
2623
|
-
/**
|
|
2624
|
-
* No description
|
|
2625
|
-
*
|
|
2626
|
-
* @tags Utils
|
|
2627
|
-
* @name PostUtilsVerifySignature
|
|
2628
|
-
* @summary Verify the SecP256K1 signature of some data
|
|
2629
|
-
* @request POST:/utils/verify-signature
|
|
2630
|
-
*/
|
|
2631
|
-
postUtilsVerifySignature: (data: VerifySignature, params: RequestParams = {}) =>
|
|
2632
|
-
this.request<boolean, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
|
|
2633
|
-
path: `/utils/verify-signature`,
|
|
2634
|
-
method: 'POST',
|
|
2635
|
-
body: data,
|
|
2636
|
-
type: ContentType.Json,
|
|
2637
|
-
format: 'json',
|
|
2638
|
-
...params
|
|
2639
|
-
}).then(convertHttpResponse),
|
|
2640
|
-
|
|
2641
|
-
/**
|
|
2642
|
-
* No description
|
|
2643
|
-
*
|
|
2644
|
-
* @tags Utils
|
|
2645
|
-
* @name PutUtilsCheckHashIndexing
|
|
2646
|
-
* @summary Check and repair the indexing of block hashes
|
|
2647
|
-
* @request PUT:/utils/check-hash-indexing
|
|
2648
|
-
*/
|
|
2649
|
-
putUtilsCheckHashIndexing: (params: RequestParams = {}) =>
|
|
2650
|
-
this.request<void, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
|
|
2651
|
-
path: `/utils/check-hash-indexing`,
|
|
2652
|
-
method: 'PUT',
|
|
2653
|
-
...params
|
|
2654
|
-
}).then(convertHttpResponse)
|
|
2655
|
-
}
|
|
2656
2624
|
miners = {
|
|
2657
2625
|
/**
|
|
2658
2626
|
* No description
|
|
@@ -2833,4 +2801,56 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
|
|
2833
2801
|
...params
|
|
2834
2802
|
}).then(convertHttpResponse)
|
|
2835
2803
|
}
|
|
2804
|
+
utils = {
|
|
2805
|
+
/**
|
|
2806
|
+
* No description
|
|
2807
|
+
*
|
|
2808
|
+
* @tags Utils
|
|
2809
|
+
* @name PostUtilsVerifySignature
|
|
2810
|
+
* @summary Verify the SecP256K1 signature of some data
|
|
2811
|
+
* @request POST:/utils/verify-signature
|
|
2812
|
+
*/
|
|
2813
|
+
postUtilsVerifySignature: (data: VerifySignature, params: RequestParams = {}) =>
|
|
2814
|
+
this.request<boolean, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
|
|
2815
|
+
path: `/utils/verify-signature`,
|
|
2816
|
+
method: 'POST',
|
|
2817
|
+
body: data,
|
|
2818
|
+
type: ContentType.Json,
|
|
2819
|
+
format: 'json',
|
|
2820
|
+
...params
|
|
2821
|
+
}).then(convertHttpResponse),
|
|
2822
|
+
|
|
2823
|
+
/**
|
|
2824
|
+
* No description
|
|
2825
|
+
*
|
|
2826
|
+
* @tags Utils
|
|
2827
|
+
* @name PostUtilsTargetToHashrate
|
|
2828
|
+
* @summary Convert a target to hashrate
|
|
2829
|
+
* @request POST:/utils/target-to-hashrate
|
|
2830
|
+
*/
|
|
2831
|
+
postUtilsTargetToHashrate: (data: TargetToHashrate, params: RequestParams = {}) =>
|
|
2832
|
+
this.request<Result, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
|
|
2833
|
+
path: `/utils/target-to-hashrate`,
|
|
2834
|
+
method: 'POST',
|
|
2835
|
+
body: data,
|
|
2836
|
+
type: ContentType.Json,
|
|
2837
|
+
format: 'json',
|
|
2838
|
+
...params
|
|
2839
|
+
}).then(convertHttpResponse),
|
|
2840
|
+
|
|
2841
|
+
/**
|
|
2842
|
+
* No description
|
|
2843
|
+
*
|
|
2844
|
+
* @tags Utils
|
|
2845
|
+
* @name PutUtilsCheckHashIndexing
|
|
2846
|
+
* @summary Check and repair the indexing of block hashes
|
|
2847
|
+
* @request PUT:/utils/check-hash-indexing
|
|
2848
|
+
*/
|
|
2849
|
+
putUtilsCheckHashIndexing: (params: RequestParams = {}) =>
|
|
2850
|
+
this.request<void, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
|
|
2851
|
+
path: `/utils/check-hash-indexing`,
|
|
2852
|
+
method: 'PUT',
|
|
2853
|
+
...params
|
|
2854
|
+
}).then(convertHttpResponse)
|
|
2855
|
+
}
|
|
2836
2856
|
}
|
package/src/api/node-provider.ts
CHANGED
|
@@ -220,8 +220,7 @@ export class NodeProvider implements NodeProviderApis {
|
|
|
220
220
|
|
|
221
221
|
guessStdInterfaceId = async (tokenId: HexString): Promise<HexString | undefined> => {
|
|
222
222
|
const address = addressFromTokenId(tokenId)
|
|
223
|
-
const
|
|
224
|
-
const rawState = await this.contracts.getContractsAddressState(addressFromTokenId(tokenId), { group })
|
|
223
|
+
const rawState = await this.contracts.getContractsAddressState(address)
|
|
225
224
|
const lastImmField = rawState.immFields.slice(-1).pop()?.value
|
|
226
225
|
const interfaceIdPrefix = '414c5048' // the hex of 'ALPH'
|
|
227
226
|
if (typeof lastImmField === 'string' && lastImmField.startsWith(interfaceIdPrefix)) {
|
package/src/contract/contract.ts
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
typeLength,
|
|
37
37
|
getDefaultValue
|
|
38
38
|
} from '../api'
|
|
39
|
+
import { CompileProjectResult } from '../api/api-alephium'
|
|
39
40
|
import {
|
|
40
41
|
SignDeployContractTxParams,
|
|
41
42
|
SignDeployContractTxResult,
|
|
@@ -53,16 +54,17 @@ import {
|
|
|
53
54
|
Eq,
|
|
54
55
|
Optional,
|
|
55
56
|
groupOfAddress,
|
|
56
|
-
addressFromContractId,
|
|
57
57
|
WebCrypto,
|
|
58
58
|
hexToBinUnsafe,
|
|
59
|
-
isDevnet
|
|
59
|
+
isDevnet,
|
|
60
|
+
addressFromContractId
|
|
60
61
|
} from '../utils'
|
|
61
62
|
import { getCurrentNodeProvider } from '../global'
|
|
62
63
|
import * as path from 'path'
|
|
63
64
|
import { EventSubscribeOptions, EventSubscription, subscribeToEvents } from './events'
|
|
64
65
|
import { ONE_ALPH } from '../constants'
|
|
65
66
|
import * as blake from 'blakejs'
|
|
67
|
+
import { parseError } from '../utils/error'
|
|
66
68
|
|
|
67
69
|
const crypto = new WebCrypto()
|
|
68
70
|
|
|
@@ -190,6 +192,28 @@ type CodeInfo = {
|
|
|
190
192
|
warnings: string[]
|
|
191
193
|
}
|
|
192
194
|
|
|
195
|
+
type SourceInfoIndexes = {
|
|
196
|
+
sourceInfo: SourceInfo
|
|
197
|
+
startIndex: number
|
|
198
|
+
endIndex: number
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function findSourceInfoAtLineNumber(sources: SourceInfo[], line: number): SourceInfoIndexes | undefined {
|
|
202
|
+
let currentLine = 0
|
|
203
|
+
const sourceInfosWithLine: SourceInfoIndexes[] = sources.map((source) => {
|
|
204
|
+
const startIndex = currentLine + 1
|
|
205
|
+
currentLine += source.sourceCode.split('\n').length
|
|
206
|
+
const endIndex = currentLine
|
|
207
|
+
return { sourceInfo: source, startIndex: startIndex, endIndex: endIndex }
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
const sourceInfo = sourceInfosWithLine.find((sourceInfoWithLine) => {
|
|
211
|
+
return line >= sourceInfoWithLine.startIndex && line <= sourceInfoWithLine.endIndex
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
return sourceInfo
|
|
215
|
+
}
|
|
216
|
+
|
|
193
217
|
export class ProjectArtifact {
|
|
194
218
|
static readonly artifactFileName = '.project.json'
|
|
195
219
|
|
|
@@ -431,6 +455,38 @@ export class Project {
|
|
|
431
455
|
return contract.artifact
|
|
432
456
|
}
|
|
433
457
|
|
|
458
|
+
private static async getCompileResult(
|
|
459
|
+
provider: NodeProvider,
|
|
460
|
+
compilerOptions: node.CompilerOptions,
|
|
461
|
+
sources: SourceInfo[]
|
|
462
|
+
): Promise<CompileProjectResult> {
|
|
463
|
+
try {
|
|
464
|
+
const sourceStr = sources.map((f) => f.sourceCode).join('\n')
|
|
465
|
+
return await provider.contracts.postContractsCompileProject({
|
|
466
|
+
code: sourceStr,
|
|
467
|
+
compilerOptions: compilerOptions
|
|
468
|
+
})
|
|
469
|
+
} catch (error) {
|
|
470
|
+
if (!(error instanceof Error)) {
|
|
471
|
+
throw error
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const parsed = parseError(error.message)
|
|
475
|
+
if (!parsed) {
|
|
476
|
+
throw error
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const sourceInfo = findSourceInfoAtLineNumber(sources, parsed.lineStart)
|
|
480
|
+
if (!sourceInfo) {
|
|
481
|
+
throw error
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const shiftIndex = parsed.lineStart - sourceInfo.startIndex + 1
|
|
485
|
+
const newError = parsed.reformat(shiftIndex, sourceInfo.sourceInfo.contractRelativePath)
|
|
486
|
+
throw new Error(newError)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
434
490
|
private static async compile(
|
|
435
491
|
fullNodeVersion: string,
|
|
436
492
|
provider: NodeProvider,
|
|
@@ -447,11 +503,8 @@ export class Project {
|
|
|
447
503
|
}
|
|
448
504
|
return acc
|
|
449
505
|
}, [])
|
|
450
|
-
|
|
451
|
-
const result = await
|
|
452
|
-
code: sourceStr,
|
|
453
|
-
compilerOptions: compilerOptions
|
|
454
|
-
})
|
|
506
|
+
|
|
507
|
+
const result = await Project.getCompileResult(provider, compilerOptions, removeDuplicates)
|
|
455
508
|
const contracts = new Map<string, Compiled<Contract>>()
|
|
456
509
|
const scripts = new Map<string, Compiled<Script>>()
|
|
457
510
|
result.contracts.forEach((contractResult) => {
|
|
@@ -1522,6 +1575,7 @@ export interface CallContractResult<R> {
|
|
|
1522
1575
|
function specialContractAddress(n: number): string {
|
|
1523
1576
|
const bytes = new Uint8Array(32).fill(0)
|
|
1524
1577
|
bytes[31] = n
|
|
1578
|
+
console.log(addressFromContractId)
|
|
1525
1579
|
return addressFromContractId(binToHex(bytes))
|
|
1526
1580
|
}
|
|
1527
1581
|
|
|
@@ -1651,9 +1705,7 @@ export async function fetchContractState<F extends Fields, I extends ContractIns
|
|
|
1651
1705
|
contract: ContractFactory<I, F>,
|
|
1652
1706
|
instance: ContractInstance
|
|
1653
1707
|
): Promise<ContractState<F>> {
|
|
1654
|
-
const contractState = await getCurrentNodeProvider().contracts.getContractsAddressState(instance.address
|
|
1655
|
-
group: instance.groupIndex
|
|
1656
|
-
})
|
|
1708
|
+
const contractState = await getCurrentNodeProvider().contracts.getContractsAddressState(instance.address)
|
|
1657
1709
|
const state = contract.contract.fromApiContractState(contractState)
|
|
1658
1710
|
return {
|
|
1659
1711
|
...state,
|
package/src/utils/address.ts
CHANGED
|
@@ -16,24 +16,179 @@ You should have received a copy of the GNU Lesser General Public License
|
|
|
16
16
|
along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { ec as EC } from 'elliptic'
|
|
20
|
+
import BN from 'bn.js'
|
|
21
|
+
import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
22
|
+
import blake from 'blakejs'
|
|
19
23
|
import bs58 from './bs58'
|
|
20
24
|
import djb2 from './djb2'
|
|
25
|
+
import { binToHex, hexToBinUnsafe } from './utils'
|
|
26
|
+
import { KeyType } from '../signer'
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
const ec = new EC('secp256k1')
|
|
29
|
+
|
|
30
|
+
export enum AddressType {
|
|
31
|
+
P2PKH = 0x00,
|
|
32
|
+
P2MPKH = 0x01,
|
|
33
|
+
P2SH = 0x02,
|
|
34
|
+
P2C = 0x03
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function validateAddress(address: string) {
|
|
38
|
+
let decoded: Uint8Array
|
|
39
|
+
try {
|
|
40
|
+
decoded = bs58.decode(address)
|
|
41
|
+
} catch (_) {
|
|
42
|
+
throw new Error('Invalid base58 string')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (decoded.length === 0) throw new Error('Address is empty')
|
|
46
|
+
const addressType = decoded[0]
|
|
47
|
+
if (addressType === AddressType.P2MPKH) {
|
|
48
|
+
// [1, n, ...hashes, m]
|
|
49
|
+
if ((decoded.length - 3) % 32 === 0) return
|
|
50
|
+
} else if (addressType === AddressType.P2PKH || addressType === AddressType.P2SH || addressType === AddressType.P2C) {
|
|
51
|
+
// [type, ...hash]
|
|
52
|
+
if (decoded.length === 33) return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
throw new Error(`Invalid address: ${address}`)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function groupOfAddress(address: string): number {
|
|
59
|
+
validateAddress(address)
|
|
60
|
+
|
|
61
|
+
const decoded = bs58.decode(address)
|
|
62
|
+
const addressType = decoded[0]
|
|
63
|
+
const addressBody = decoded.slice(1)
|
|
64
|
+
|
|
65
|
+
if (addressType == AddressType.P2PKH) {
|
|
66
|
+
return groupOfP2pkhAddress(addressBody)
|
|
67
|
+
} else if (addressType == AddressType.P2MPKH) {
|
|
68
|
+
return groupOfP2mpkhAddress(addressBody)
|
|
69
|
+
} else if (addressType == AddressType.P2SH) {
|
|
70
|
+
return groupOfP2shAddress(addressBody)
|
|
71
|
+
} else {
|
|
72
|
+
// Contract Address
|
|
73
|
+
const id = contractIdFromAddress(address)
|
|
74
|
+
return id[`${id.length - 1}`]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function groupOfAddressBytes(bytes: Uint8Array): number {
|
|
79
|
+
const hint = djb2(bytes) | 1
|
|
80
|
+
const hash = xorByte(hint)
|
|
81
|
+
const group = hash % TOTAL_NUMBER_OF_GROUPS
|
|
27
82
|
return group
|
|
28
83
|
}
|
|
29
84
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
85
|
+
// Pay to public key hash address
|
|
86
|
+
function groupOfP2pkhAddress(address: Uint8Array): number {
|
|
87
|
+
return groupOfAddressBytes(address)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Pay to multiple public key hash address
|
|
91
|
+
function groupOfP2mpkhAddress(address: Uint8Array): number {
|
|
92
|
+
return groupOfAddressBytes(address.slice(1, 33))
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Pay to script hash address
|
|
96
|
+
function groupOfP2shAddress(address: Uint8Array): number {
|
|
97
|
+
return groupOfAddressBytes(address)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function contractIdFromAddress(address: string): Uint8Array {
|
|
101
|
+
return idFromAddress(address)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function tokenIdFromAddress(address: string): Uint8Array {
|
|
105
|
+
return idFromAddress(address)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function idFromAddress(address: string): Uint8Array {
|
|
109
|
+
const decoded = bs58.decode(address)
|
|
110
|
+
|
|
111
|
+
if (decoded.length == 0) throw new Error('Address string is empty')
|
|
112
|
+
const addressType = decoded[0]
|
|
113
|
+
const addressBody = decoded.slice(1)
|
|
114
|
+
|
|
115
|
+
if (addressType == AddressType.P2C) {
|
|
116
|
+
return addressBody
|
|
117
|
+
} else {
|
|
118
|
+
throw new Error(`Invalid contract address type: ${addressType}`)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function groupOfPrivateKey(privateKey: string, keyType?: KeyType): number {
|
|
123
|
+
return groupOfAddress(addressFromPublicKey(publicKeyFromPrivateKey(privateKey, keyType), keyType))
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function publicKeyFromPrivateKey(privateKey: string, _keyType?: KeyType): string {
|
|
127
|
+
const keyType = _keyType ?? 'default'
|
|
128
|
+
|
|
129
|
+
if (keyType === 'default') {
|
|
130
|
+
const key = ec.keyFromPrivate(privateKey)
|
|
131
|
+
return key.getPublic(true, 'hex')
|
|
132
|
+
} else {
|
|
133
|
+
return ec.g.mul(new BN(privateKey, 16)).encode('hex', true).slice(2)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function addressFromPublicKey(publicKey: string, _keyType?: KeyType): string {
|
|
138
|
+
const keyType = _keyType ?? 'default'
|
|
139
|
+
|
|
140
|
+
if (keyType === 'default') {
|
|
141
|
+
const addressType = Buffer.from([AddressType.P2PKH])
|
|
142
|
+
const hash = Buffer.from(blake.blake2b(Buffer.from(publicKey, 'hex'), undefined, 32))
|
|
143
|
+
const bytes = Buffer.concat([addressType, hash])
|
|
144
|
+
return bs58.encode(bytes)
|
|
145
|
+
} else {
|
|
146
|
+
const lockupScript = Buffer.from(`0101000000000458144020${publicKey}8685`, 'hex')
|
|
147
|
+
return addressFromScript(lockupScript)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function addressFromScript(script: Uint8Array): string {
|
|
152
|
+
const scriptHash = blake.blake2b(script, undefined, 32)
|
|
153
|
+
const addressType = Buffer.from([AddressType.P2SH])
|
|
154
|
+
return bs58.encode(Buffer.concat([addressType, scriptHash]))
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function addressFromContractId(contractId: string): string {
|
|
158
|
+
const addressType = Buffer.from([AddressType.P2C])
|
|
159
|
+
const hash = Buffer.from(hexToBinUnsafe(contractId))
|
|
160
|
+
const bytes = Buffer.concat([addressType, hash])
|
|
161
|
+
return bs58.encode(bytes)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function addressFromTokenId(tokenId: string): string {
|
|
165
|
+
const contractId = tokenId // contract ID is the same as token ID
|
|
166
|
+
return addressFromContractId(contractId)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function contractIdFromTx(txId: string, outputIndex: number): string {
|
|
170
|
+
const txIdBin = hexToBinUnsafe(txId)
|
|
171
|
+
const data = Buffer.concat([txIdBin, Buffer.from([outputIndex])])
|
|
172
|
+
const hash = blake.blake2b(data, undefined, 32)
|
|
173
|
+
return binToHex(hash)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function subContractId(parentContractId: string, pathInHex: string, group: number): string {
|
|
177
|
+
if (group < 0 || group >= TOTAL_NUMBER_OF_GROUPS) {
|
|
178
|
+
throw new Error(`Invalid group ${group}`)
|
|
179
|
+
}
|
|
180
|
+
const data = Buffer.concat([hexToBinUnsafe(parentContractId), hexToBinUnsafe(pathInHex)])
|
|
181
|
+
const bytes = Buffer.concat([
|
|
182
|
+
blake.blake2b(blake.blake2b(data, undefined, 32), undefined, 32).slice(0, -1),
|
|
183
|
+
Buffer.from([group])
|
|
184
|
+
])
|
|
185
|
+
return binToHex(bytes)
|
|
35
186
|
}
|
|
36
187
|
|
|
37
|
-
function
|
|
38
|
-
|
|
188
|
+
export function xorByte(intValue: number): number {
|
|
189
|
+
const byte0 = (intValue >> 24) & 0xff
|
|
190
|
+
const byte1 = (intValue >> 16) & 0xff
|
|
191
|
+
const byte2 = (intValue >> 8) & 0xff
|
|
192
|
+
const byte3 = intValue & 0xff
|
|
193
|
+
return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff
|
|
39
194
|
}
|