@alephium/web3 0.21.1 → 0.22.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.
@@ -963,7 +963,7 @@ export declare class HttpClient<SecurityDataType = unknown> {
963
963
  }
964
964
  /**
965
965
  * @title Alephium API
966
- * @version 2.5.3
966
+ * @version 2.5.5
967
967
  * @baseUrl ../
968
968
  */
969
969
  export declare class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
@@ -1347,6 +1347,7 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
1347
1347
  * @request GET:/blockflow/is-block-in-main-chain
1348
1348
  */
1349
1349
  getBlockflowIsBlockInMainChain: (query: {
1350
+ /** @format block-hash */
1350
1351
  blockHash: string;
1351
1352
  }, params?: RequestParams) => Promise<boolean>;
1352
1353
  /**
@@ -1480,6 +1481,7 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
1480
1481
  * @request GET:/transactions/status
1481
1482
  */
1482
1483
  getTransactionsStatus: (query: {
1484
+ /** @format 32-byte-hash */
1483
1485
  txId: string;
1484
1486
  /** @format int32 */
1485
1487
  fromGroup?: number;
@@ -1515,6 +1517,7 @@ export declare class Api<SecurityDataType extends unknown> extends HttpClient<Se
1515
1517
  * @request PUT:/mempool/transactions/rebroadcast
1516
1518
  */
1517
1519
  putMempoolTransactionsRebroadcast: (query: {
1520
+ /** @format 32-byte-hash */
1518
1521
  txId: string;
1519
1522
  }, params?: RequestParams) => Promise<void>;
1520
1523
  /**
@@ -151,7 +151,7 @@ class HttpClient {
151
151
  exports.HttpClient = HttpClient;
152
152
  /**
153
153
  * @title Alephium API
154
- * @version 2.5.3
154
+ * @version 2.5.5
155
155
  * @baseUrl ../
156
156
  */
157
157
  class Api extends HttpClient {
@@ -57,10 +57,46 @@ class NodeProvider {
57
57
  this.fetchNFTMetaData = async (tokenId) => {
58
58
  const address = (0, utils_1.addressFromTokenId)(tokenId);
59
59
  const group = (0, utils_1.groupOfAddress)(address);
60
- const result = await this.contracts.postContractsCallContract({ methodIndex: 0, group, address });
61
- return {
62
- tokenUri: (0, utils_1.hexToString)((0, contract_1.tryGetCallResult)(result).returns[0].value)
63
- };
60
+ const calls = Array.from([0, 1], (index) => ({ methodIndex: index, group: group, address: address }));
61
+ const result = await this.contracts.postContractsMulticallContract({
62
+ calls: calls
63
+ });
64
+ const tokenUri = (0, utils_1.hexToString)((0, contract_1.tryGetCallResult)(result.results[0]).returns[0].value);
65
+ const collectionIndexResult = result.results[1];
66
+ if (collectionIndexResult.type === 'CallContractSucceeded') {
67
+ const successfulCollectionIndexResult = result.results[1];
68
+ const contractIdReturnResult = successfulCollectionIndexResult.returns[0];
69
+ if (contractIdReturnResult === undefined) {
70
+ throw new Error('Deprecated NFT contract');
71
+ }
72
+ const collectionId = successfulCollectionIndexResult.returns[0].value;
73
+ if (collectionId === undefined || !(0, utils_1.isHexString)(collectionId) || collectionId.length !== 64) {
74
+ throw new Error('Deprecated NFT contract');
75
+ }
76
+ const nftIndexReturnResult = successfulCollectionIndexResult.returns[1];
77
+ if (nftIndexReturnResult === undefined) {
78
+ throw new Error('Deprecated NFT contract');
79
+ }
80
+ const nftIndex = (0, utils_1.toNonNegativeBigInt)(nftIndexReturnResult.value);
81
+ if (nftIndex === undefined) {
82
+ throw new Error('Deprecated NFT contract');
83
+ }
84
+ // If there are more return values, it is also a deprecated NFT contract
85
+ const thirdResult = successfulCollectionIndexResult.returns[2];
86
+ if (thirdResult !== undefined) {
87
+ throw new Error('Deprecated NFT contract');
88
+ }
89
+ return { tokenUri, collectionId, nftIndex };
90
+ }
91
+ else {
92
+ const failedCollectionIndexResult = result.results[1];
93
+ if (failedCollectionIndexResult.error.startsWith('VM execution error: InvalidMethodIndex')) {
94
+ throw new Error('Deprecated NFT contract');
95
+ }
96
+ else {
97
+ throw new Error(`Failed to call contract, error: ${failedCollectionIndexResult.error}`);
98
+ }
99
+ }
64
100
  };
65
101
  // Only use this when the contract follows the NFT collection interface, check `guessFollowsNFTCollectionStd` first
66
102
  this.fetchNFTCollectionMetaData = async (contractId) => {
@@ -44,6 +44,8 @@ export interface FungibleTokenMetaData {
44
44
  totalSupply: Number256;
45
45
  }
46
46
  export interface NFTMetaData {
47
+ collectionId: string;
48
+ nftIndex: Number256;
47
49
  tokenUri: string;
48
50
  }
49
51
  export interface NFTCollectionMetaData {
@@ -12,6 +12,7 @@ export declare function encodeHexSignature(rHex: string, sHex: string): string;
12
12
  export declare function signatureDecode(ec: EC, signature: string): SignatureInput;
13
13
  export declare function xorByte(intValue: number): number;
14
14
  export declare function isHexString(input: string): boolean;
15
+ export declare function toNonNegativeBigInt(input: string): bigint | undefined;
15
16
  export declare function groupOfAddress(address: string): number;
16
17
  export declare function contractIdFromAddress(address: string): Uint8Array;
17
18
  export declare function tokenIdFromAddress(address: string): Uint8Array;
@@ -20,7 +20,7 @@ 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.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.isHexString = exports.xorByte = exports.signatureDecode = exports.encodeHexSignature = exports.encodeSignature = exports.networkIds = void 0;
23
+ exports.assertType = exports.sleep = exports.hexToString = exports.stringToHex = exports.blockChainIndex = exports.subContractId = exports.contractIdFromTx = exports.addressFromTokenId = exports.addressFromContractId = exports.addressFromPublicKey = exports.publicKeyFromPrivateKey = exports.groupOfPrivateKey = exports.binToHex = exports.hexToBinUnsafe = exports.tokenIdFromAddress = exports.contractIdFromAddress = exports.groupOfAddress = exports.toNonNegativeBigInt = exports.isHexString = exports.xorByte = 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
26
  const blakejs_1 = __importDefault(require("blakejs"));
@@ -72,6 +72,16 @@ function isHexString(input) {
72
72
  return input.length % 2 === 0 && /^[0-9a-fA-F]*$/.test(input);
73
73
  }
74
74
  exports.isHexString = isHexString;
75
+ function toNonNegativeBigInt(input) {
76
+ try {
77
+ const bigIntValue = BigInt(input);
78
+ return bigIntValue < 0n ? undefined : bigIntValue;
79
+ }
80
+ catch {
81
+ return undefined;
82
+ }
83
+ }
84
+ exports.toNonNegativeBigInt = toNonNegativeBigInt;
75
85
  var AddressType;
76
86
  (function (AddressType) {
77
87
  AddressType[AddressType["P2PKH"] = 0] = "P2PKH";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alephium/web3",
3
- "version": "0.21.1",
3
+ "version": "0.22.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.5.3",
30
+ "alephium_version": "2.5.5",
31
31
  "explorer_backend_version": "1.15.1"
32
32
  },
33
33
  "type": "commonjs",
@@ -1256,7 +1256,7 @@ export class HttpClient<SecurityDataType = unknown> {
1256
1256
 
1257
1257
  /**
1258
1258
  * @title Alephium API
1259
- * @version 2.5.3
1259
+ * @version 2.5.5
1260
1260
  * @baseUrl ../
1261
1261
  */
1262
1262
  export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
@@ -1955,6 +1955,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1955
1955
  */
1956
1956
  getBlockflowIsBlockInMainChain: (
1957
1957
  query: {
1958
+ /** @format block-hash */
1958
1959
  blockHash: string
1959
1960
  },
1960
1961
  params: RequestParams = {}
@@ -2209,6 +2210,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
2209
2210
  */
2210
2211
  getTransactionsStatus: (
2211
2212
  query: {
2213
+ /** @format 32-byte-hash */
2212
2214
  txId: string
2213
2215
  /** @format int32 */
2214
2216
  fromGroup?: number
@@ -2270,6 +2272,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
2270
2272
  */
2271
2273
  putMempoolTransactionsRebroadcast: (
2272
2274
  query: {
2275
+ /** @format 32-byte-hash */
2273
2276
  txId: string
2274
2277
  },
2275
2278
  params: RequestParams = {}
@@ -26,9 +26,16 @@ import {
26
26
  NFTCollectionMetaData,
27
27
  StdInterfaceIds
28
28
  } from './types'
29
- import { Api as NodeApi } from './api-alephium'
29
+ import { Api as NodeApi, CallContractFailed, CallContractSucceeded } from './api-alephium'
30
30
  import { HexString, tryGetCallResult } from '../contract'
31
- import { addressFromContractId, addressFromTokenId, groupOfAddress, hexToString } from '../utils'
31
+ import {
32
+ addressFromContractId,
33
+ addressFromTokenId,
34
+ groupOfAddress,
35
+ hexToString,
36
+ isHexString,
37
+ toNonNegativeBigInt
38
+ } from '../utils'
32
39
 
33
40
  function initializeNodeApi(baseUrl: string, apiKey?: string, customFetch?: typeof fetch): NodeApi<string> {
34
41
  const nodeApi = new NodeApi<string>({
@@ -129,9 +136,46 @@ export class NodeProvider implements NodeProviderApis {
129
136
  fetchNFTMetaData = async (tokenId: HexString): Promise<NFTMetaData> => {
130
137
  const address = addressFromTokenId(tokenId)
131
138
  const group = groupOfAddress(address)
132
- const result = await this.contracts.postContractsCallContract({ methodIndex: 0, group, address })
133
- return {
134
- tokenUri: hexToString(tryGetCallResult(result).returns[0].value as any as string)
139
+ const calls = Array.from([0, 1], (index) => ({ methodIndex: index, group: group, address: address }))
140
+ const result = await this.contracts.postContractsMulticallContract({
141
+ calls: calls
142
+ })
143
+ const tokenUri = hexToString(tryGetCallResult(result.results[0]).returns[0].value as any as string)
144
+ const collectionIndexResult = result.results[1]
145
+ if (collectionIndexResult.type === 'CallContractSucceeded') {
146
+ const successfulCollectionIndexResult = result.results[1] as CallContractSucceeded
147
+ const contractIdReturnResult = successfulCollectionIndexResult.returns[0]
148
+ if (contractIdReturnResult === undefined) {
149
+ throw new Error('Deprecated NFT contract')
150
+ }
151
+ const collectionId = successfulCollectionIndexResult.returns[0].value as any as string
152
+ if (collectionId === undefined || !isHexString(collectionId) || collectionId.length !== 64) {
153
+ throw new Error('Deprecated NFT contract')
154
+ }
155
+
156
+ const nftIndexReturnResult = successfulCollectionIndexResult.returns[1]
157
+ if (nftIndexReturnResult === undefined) {
158
+ throw new Error('Deprecated NFT contract')
159
+ }
160
+ const nftIndex = toNonNegativeBigInt(nftIndexReturnResult.value as any as string)
161
+ if (nftIndex === undefined) {
162
+ throw new Error('Deprecated NFT contract')
163
+ }
164
+
165
+ // If there are more return values, it is also a deprecated NFT contract
166
+ const thirdResult = successfulCollectionIndexResult.returns[2]
167
+ if (thirdResult !== undefined) {
168
+ throw new Error('Deprecated NFT contract')
169
+ }
170
+
171
+ return { tokenUri, collectionId, nftIndex }
172
+ } else {
173
+ const failedCollectionIndexResult = result.results[1] as CallContractFailed
174
+ if (failedCollectionIndexResult.error.startsWith('VM execution error: InvalidMethodIndex')) {
175
+ throw new Error('Deprecated NFT contract')
176
+ } else {
177
+ throw new Error(`Failed to call contract, error: ${failedCollectionIndexResult.error}`)
178
+ }
135
179
  }
136
180
  }
137
181
 
package/src/api/types.ts CHANGED
@@ -298,6 +298,8 @@ export interface FungibleTokenMetaData {
298
298
  }
299
299
 
300
300
  export interface NFTMetaData {
301
+ collectionId: string
302
+ nftIndex: Number256
301
303
  tokenUri: string
302
304
  }
303
305
 
@@ -75,6 +75,15 @@ export function isHexString(input: string): boolean {
75
75
  return input.length % 2 === 0 && /^[0-9a-fA-F]*$/.test(input)
76
76
  }
77
77
 
78
+ export function toNonNegativeBigInt(input: string): bigint | undefined {
79
+ try {
80
+ const bigIntValue = BigInt(input)
81
+ return bigIntValue < 0n ? undefined : bigIntValue
82
+ } catch {
83
+ return undefined
84
+ }
85
+ }
86
+
78
87
  enum AddressType {
79
88
  P2PKH = 0x00,
80
89
  P2MPKH = 0x01,
@@ -26,4 +26,7 @@ Interface INFTCollection {
26
26
  pub fn totalSupply() -> U256
27
27
 
28
28
  pub fn nftByIndex(index: U256) -> INFT
29
+
30
+ // Validates that the NFT is part of the collection, otherwise throws exception.
31
+ pub fn validateNFT(nftId: ByteVec, nftIndex: U256) -> ()
29
32
  }
@@ -22,4 +22,7 @@ Interface INFT {
22
22
  // }
23
23
  // }
24
24
  pub fn getTokenUri() -> ByteVec
25
+
26
+ // Returns collection id and index of the NFT in the collection.
27
+ pub fn getCollectionIndex() -> (ByteVec, U256)
25
28
  }