@alephium/web3 0.30.1 → 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.
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /*
3
+ Copyright 2018 - 2022 The Alephium Authors
4
+ This file is part of the alephium project.
5
+
6
+ The library is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ The library is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.parseError = void 0;
21
+ class CompilationError {
22
+ constructor(lineStart, column, errorType, line, codeLine, errorIndicator, message, additionalLine1, additionalLine2) {
23
+ this.lineStart = lineStart;
24
+ this.column = column;
25
+ this.errorType = errorType;
26
+ this.line = line;
27
+ this.codeLine = codeLine;
28
+ this.errorIndicator = errorIndicator;
29
+ this.message = message;
30
+ this.additionalLine1 = additionalLine1;
31
+ this.additionalLine2 = additionalLine2;
32
+ }
33
+ reformat(line, file) {
34
+ const spaces = `${line}`.replace(/\d/g, ' ');
35
+ const newError = `${file} (${line}:${this.column}): ${this.errorType}
36
+ ${line} |${this.codeLine}
37
+ ${spaces} |${this.errorIndicator}
38
+ ${spaces} |${this.message}`;
39
+ if (this.additionalLine1 && this.additionalLine2) {
40
+ return `${newError}\n${spaces} |${this.additionalLine1}\n${spaces} |${this.additionalLine2}`;
41
+ }
42
+ else {
43
+ return newError;
44
+ }
45
+ }
46
+ }
47
+ const errorRegex = /error \((\d+):(\d+)\):\s*(.*)\n\s*(\d+)\s*\|(.*)\n.*\|(.*)\n\s*\|(.*)(?:\n\s*\|(.*)\n\s*\|(.*))?/;
48
+ function parseError(error) {
49
+ const match = error.match(errorRegex);
50
+ if (match) {
51
+ const lineStart = parseInt(match[1]);
52
+ const column = parseInt(match[2]);
53
+ const errorType = match[3];
54
+ const line = parseInt(match[4]);
55
+ const codeLine = match[5];
56
+ const errorIndicator = match[6];
57
+ const message = match[7];
58
+ const additionalLine1 = match[8];
59
+ const additionalLine2 = match[9];
60
+ return new CompilationError(lineStart, column, errorType, line, codeLine, errorIndicator, message, additionalLine1, additionalLine2);
61
+ }
62
+ else {
63
+ undefined;
64
+ }
65
+ }
66
+ exports.parseError = parseError;
@@ -1,6 +1,5 @@
1
1
  import { ec as EC, SignatureInput } from 'elliptic';
2
2
  import BN from 'bn.js';
3
- import { KeyType } from '../signer';
4
3
  import { HexString } from '../contract';
5
4
  export declare const networkIds: readonly ["mainnet", "testnet", "devnet"];
6
5
  export type NetworkId = (typeof networkIds)[number];
@@ -10,28 +9,10 @@ export declare function encodeSignature(signature: EC.Signature | {
10
9
  }): string;
11
10
  export declare function encodeHexSignature(rHex: string, sHex: string): string;
12
11
  export declare function signatureDecode(ec: EC, signature: string): SignatureInput;
13
- export declare function xorByte(intValue: number): number;
14
12
  export declare function isHexString(input: string): boolean;
15
13
  export declare function toNonNegativeBigInt(input: string): bigint | undefined;
16
- export declare enum AddressType {
17
- P2PKH = 0,
18
- P2MPKH = 1,
19
- P2SH = 2,
20
- P2C = 3
21
- }
22
- export declare function groupOfAddress(address: string): number;
23
- export declare function contractIdFromAddress(address: string): Uint8Array;
24
- export declare function tokenIdFromAddress(address: string): Uint8Array;
25
14
  export declare function hexToBinUnsafe(hex: string): Uint8Array;
26
15
  export declare function binToHex(bin: Uint8Array): string;
27
- export declare function groupOfPrivateKey(privateKey: string, keyType?: KeyType): number;
28
- export declare function publicKeyFromPrivateKey(privateKey: string, _keyType?: KeyType): string;
29
- export declare function addressFromPublicKey(publicKey: string, _keyType?: KeyType): string;
30
- export declare function addressFromScript(script: Uint8Array): string;
31
- export declare function addressFromContractId(contractId: string): string;
32
- export declare function addressFromTokenId(tokenId: string): string;
33
- export declare function contractIdFromTx(txId: string, outputIndex: number): string;
34
- export declare function subContractId(parentContractId: string, pathInHex: string, group: number): string;
35
16
  export declare function blockChainIndex(blockHash: HexString): {
36
17
  fromGroup: number;
37
18
  toGroup: number;
@@ -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.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromScript = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.AddressType = exports.toNonNegativeBigInt = exports.isHexString = exports.xorByte = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = exports.networkIds = void 0;
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.30.1",
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.4",
30
+ "alephium_version": "2.8.5",
31
31
  "explorer_backend_version": "1.16.1"
32
32
  },
33
33
  "type": "commonjs",
@@ -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.4
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
  }
@@ -182,8 +182,8 @@ export class NodeProvider implements NodeProviderApis {
182
182
  }
183
183
 
184
184
  // Only use this when the contract follows the NFT collection interface, check `guessFollowsNFTCollectionStd` first
185
- fetchNFTCollectionMetaData = async (contractId: HexString): Promise<NFTCollectionMetaData> => {
186
- const address = addressFromContractId(contractId)
185
+ fetchNFTCollectionMetaData = async (collectionId: HexString): Promise<NFTCollectionMetaData> => {
186
+ const address = addressFromContractId(collectionId)
187
187
  const group = groupOfAddress(address)
188
188
  const calls = Array.from([0, 1], (index) => ({ methodIndex: index, group: group, address: address }))
189
189
  const result = await this.contracts.postContractsMulticallContract({ calls })
@@ -194,10 +194,33 @@ export class NodeProvider implements NodeProviderApis {
194
194
  }
195
195
  }
196
196
 
197
+ // Only use this when the contract follows the NFT collection with royalty interface, check `guessFollowsNFTCollectionWithRoyaltyStd` first
198
+ fetchNFTRoyaltyAmount = async (collectionId: HexString, tokenId: HexString, salePrice: bigint): Promise<bigint> => {
199
+ const address = addressFromContractId(collectionId)
200
+ const group = groupOfAddress(address)
201
+ const apiResult = await this.contracts.postContractsCallContract({
202
+ address: address,
203
+ group: group,
204
+ methodIndex: 4,
205
+ args: [
206
+ {
207
+ type: 'ByteVec',
208
+ value: tokenId
209
+ },
210
+ {
211
+ type: 'U256',
212
+ value: salePrice.toString()
213
+ }
214
+ ]
215
+ })
216
+
217
+ const result = tryGetCallResult(apiResult)
218
+ return BigInt(result.returns[0].value as any as string)
219
+ }
220
+
197
221
  guessStdInterfaceId = async (tokenId: HexString): Promise<HexString | undefined> => {
198
222
  const address = addressFromTokenId(tokenId)
199
- const group = groupOfAddress(address)
200
- const rawState = await this.contracts.getContractsAddressState(addressFromTokenId(tokenId), { group })
223
+ const rawState = await this.contracts.getContractsAddressState(address)
201
224
  const lastImmField = rawState.immFields.slice(-1).pop()?.value
202
225
  const interfaceIdPrefix = '414c5048' // the hex of 'ALPH'
203
226
  if (typeof lastImmField === 'string' && lastImmField.startsWith(interfaceIdPrefix)) {
@@ -212,6 +235,11 @@ export class NodeProvider implements NodeProviderApis {
212
235
  return !!interfaceId && interfaceId.startsWith(StdInterfaceIds.NFTCollection)
213
236
  }
214
237
 
238
+ guessFollowsNFTCollectionWithRoyaltyStd = async (contractId: HexString): Promise<boolean> => {
239
+ const interfaceId = await this.guessStdInterfaceId(contractId)
240
+ return interfaceId === StdInterfaceIds.NFTCollectionWithRoyalty
241
+ }
242
+
215
243
  guessStdTokenType = async (tokenId: HexString): Promise<'fungible' | 'non-fungible' | undefined> => {
216
244
  const interfaceId = await this.guessStdInterfaceId(tokenId)
217
245
  switch (interfaceId) {
package/src/api/types.ts CHANGED
@@ -343,12 +343,10 @@ export interface NFTTokenUriMetaData {
343
343
  name: string
344
344
  description?: string
345
345
  image: string
346
- attributes?: [
347
- {
348
- trait_type: string
349
- value: string | number | boolean
350
- }
351
- ]
346
+ attributes?: {
347
+ trait_type: string
348
+ value: string | number | boolean
349
+ }[]
352
350
  }
353
351
 
354
352
  export interface NFTCollectionUriMetaData {
@@ -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
- const sourceStr = removeDuplicates.map((f) => f.sourceCode).join('\n')
451
- const result = await provider.contracts.postContractsCompileProject({
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,