@alephium/web3 0.21.2 → 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.
@@ -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.2",
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",
@@ -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
  }