@alephium/web3 0.15.1 → 0.16.1

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.
@@ -43,6 +43,15 @@ export interface AddressInfo {
43
43
  txNumber: number
44
44
  }
45
45
 
46
+ export interface AddressTokenBalance {
47
+ /** @format 32-byte-hash */
48
+ tokenId: string
49
+ /** @format uint256 */
50
+ balance: string
51
+ /** @format uint256 */
52
+ lockedBalance: string
53
+ }
54
+
46
55
  export interface AssetOutput {
47
56
  /** @format int32 */
48
57
  hint: number
@@ -71,9 +80,9 @@ export interface BlockEntryLite {
71
80
  hash: string
72
81
  /** @format int64 */
73
82
  timestamp: number
74
- /** @format int32 */
83
+ /** @format group-index */
75
84
  chainFrom: number
76
- /** @format int32 */
85
+ /** @format group-index */
77
86
  chainTo: number
78
87
  /** @format int32 */
79
88
  height: number
@@ -121,6 +130,10 @@ export interface Event {
121
130
  export interface ExplorerInfo {
122
131
  releaseVersion: string
123
132
  commit: string
133
+ /** @format int32 */
134
+ migrationsVersion: number
135
+ /** @format int64 */
136
+ lastFinalizedInputTime: number
124
137
  }
125
138
 
126
139
  export interface Hashrate {
@@ -166,9 +179,9 @@ export interface LogbackValue {
166
179
  export interface MempoolTransaction {
167
180
  /** @format 32-byte-hash */
168
181
  hash: string
169
- /** @format int32 */
182
+ /** @format group-index */
170
183
  chainFrom: number
171
- /** @format int32 */
184
+ /** @format group-index */
172
185
  chainTo: number
173
186
  inputs?: Input[]
174
187
  outputs?: Output[]
@@ -197,9 +210,9 @@ export interface OutputRef {
197
210
  export interface PendingTransaction {
198
211
  /** @format 32-byte-hash */
199
212
  hash: string
200
- /** @format int32 */
213
+ /** @format group-index */
201
214
  chainFrom: number
202
- /** @format int32 */
215
+ /** @format group-index */
203
216
  chainTo: number
204
217
  inputs?: Input[]
205
218
  outputs?: Output[]
@@ -630,8 +643,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
630
643
  * @format int32
631
644
  */
632
645
  limit?: number
633
- /** Reverse pagination */
634
- reverse?: boolean
635
646
  },
636
647
  params: RequestParams = {}
637
648
  ) =>
@@ -695,8 +706,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
695
706
  * @format int32
696
707
  */
697
708
  limit?: number
698
- /** Reverse pagination */
699
- reverse?: boolean
700
709
  },
701
710
  params: RequestParams = {}
702
711
  ) =>
@@ -727,8 +736,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
727
736
  * @format int32
728
737
  */
729
738
  limit?: number
730
- /** Reverse pagination */
731
- reverse?: boolean
732
739
  },
733
740
  data?: string[],
734
741
  params: RequestParams = {}
@@ -773,8 +780,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
773
780
  * @format int32
774
781
  */
775
782
  limit?: number
776
- /** Reverse pagination */
777
- reverse?: boolean
778
783
  },
779
784
  params: RequestParams = {}
780
785
  ) =>
@@ -854,8 +859,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
854
859
  * @format int32
855
860
  */
856
861
  limit?: number
857
- /** Reverse pagination */
858
- reverse?: boolean
859
862
  },
860
863
  params: RequestParams = {}
861
864
  ) =>
@@ -888,8 +891,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
888
891
  * @format int32
889
892
  */
890
893
  limit?: number
891
- /** Reverse pagination */
892
- reverse?: boolean
893
894
  },
894
895
  params: RequestParams = {}
895
896
  ) =>
@@ -909,13 +910,50 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
909
910
  * @request GET:/addresses/{address}/tokens/{token_id}/balance
910
911
  */
911
912
  getAddressesAddressTokensTokenIdBalance: (address: string, tokenId: string, params: RequestParams = {}) =>
912
- this.request<AddressBalance, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
913
+ this.request<
914
+ AddressTokenBalance,
915
+ BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable
916
+ >({
913
917
  path: `/addresses/${address}/tokens/${tokenId}/balance`,
914
918
  method: 'GET',
915
919
  format: 'json',
916
920
  ...params
917
921
  }).then(convertHttpResponse),
918
922
 
923
+ /**
924
+ * @description Get address tokens with balance
925
+ *
926
+ * @tags Addresses
927
+ * @name GetAddressesAddressTokensBalance
928
+ * @request GET:/addresses/{address}/tokens-balance
929
+ */
930
+ getAddressesAddressTokensBalance: (
931
+ address: string,
932
+ query?: {
933
+ /**
934
+ * Page number
935
+ * @format int32
936
+ */
937
+ page?: number
938
+ /**
939
+ * Number of items per page
940
+ * @format int32
941
+ */
942
+ limit?: number
943
+ },
944
+ params: RequestParams = {}
945
+ ) =>
946
+ this.request<
947
+ AddressTokenBalance[],
948
+ BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable
949
+ >({
950
+ path: `/addresses/${address}/tokens-balance`,
951
+ method: 'GET',
952
+ query: query,
953
+ format: 'json',
954
+ ...params
955
+ }).then(convertHttpResponse),
956
+
919
957
  /**
920
958
  * @description Are the addresses used (at least 1 transaction)
921
959
  *
@@ -1046,8 +1084,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1046
1084
  * @format int32
1047
1085
  */
1048
1086
  limit?: number
1049
- /** Reverse pagination */
1050
- reverse?: boolean
1051
1087
  },
1052
1088
  params: RequestParams = {}
1053
1089
  ) =>
@@ -1171,8 +1207,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1171
1207
  * @format int32
1172
1208
  */
1173
1209
  limit?: number
1174
- /** Reverse pagination */
1175
- reverse?: boolean
1176
1210
  },
1177
1211
  params: RequestParams = {}
1178
1212
  ) =>
@@ -1207,8 +1241,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1207
1241
  * @format int32
1208
1242
  */
1209
1243
  limit?: number
1210
- /** Reverse pagination */
1211
- reverse?: boolean
1212
1244
  },
1213
1245
  params: RequestParams = {}
1214
1246
  ) =>
@@ -1240,8 +1272,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1240
1272
  * @format int32
1241
1273
  */
1242
1274
  limit?: number
1243
- /** Reverse pagination */
1244
- reverse?: boolean
1245
1275
  },
1246
1276
  params: RequestParams = {}
1247
1277
  ) =>
@@ -1389,8 +1419,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1389
1419
  * @format int32
1390
1420
  */
1391
1421
  limit?: number
1392
- /** Reverse pagination */
1393
- reverse?: boolean
1394
1422
  },
1395
1423
  params: RequestParams = {}
1396
1424
  ) =>
@@ -1423,8 +1451,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1423
1451
  * @format int32
1424
1452
  */
1425
1453
  limit?: number
1426
- /** Reverse pagination */
1427
- reverse?: boolean
1428
1454
  },
1429
1455
  params: RequestParams = {}
1430
1456
  ) =>
@@ -1472,8 +1498,6 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1472
1498
  * @format int32
1473
1499
  */
1474
1500
  limit?: number
1475
- /** Reverse pagination */
1476
- reverse?: boolean
1477
1501
  },
1478
1502
  params: RequestParams = {}
1479
1503
  ) =>
package/src/api/types.ts CHANGED
@@ -16,7 +16,7 @@ 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 { assertType, bs58, Eq } from '../utils'
19
+ import { assertType, bs58, Eq, isBase58, isHexString } from '../utils'
20
20
  import * as node from './api-alephium'
21
21
 
22
22
  export type Number256 = bigint | string
@@ -58,10 +58,15 @@ export function toApiNumber256(v: Val): string {
58
58
  if ((typeof v === 'number' && Number.isInteger(v)) || typeof v === 'bigint') {
59
59
  return v.toString()
60
60
  } else if (typeof v === 'string') {
61
- return v
62
- } else {
63
- throw new Error(`Invalid 256 bit number: ${v}`)
61
+ try {
62
+ if (BigInt(v).toString() === v) {
63
+ return v
64
+ }
65
+ } catch (_) {
66
+ throw new Error(`Invalid value: ${v}, expected a 256 bit number`)
67
+ }
64
68
  }
69
+ throw new Error(`Invalid value: ${v}, expected a 256 bit number`)
65
70
  }
66
71
 
67
72
  export function toApiNumber256Optional(v?: Val): string | undefined {
@@ -72,9 +77,12 @@ export function fromApiNumber256(n: string): bigint {
72
77
  return BigInt(n)
73
78
  }
74
79
 
75
- // TODO: check hex string
76
80
  export function toApiByteVec(v: Val): string {
77
- if (typeof v === 'string') {
81
+ if (typeof v !== 'string') {
82
+ throw new Error(`Invalid value: ${v}, expected a hex-string`)
83
+ }
84
+ if (isHexString(v)) return v
85
+ if (isBase58(v)) {
78
86
  // try to convert from address to contract id
79
87
  try {
80
88
  const address = bs58.decode(v)
@@ -82,12 +90,10 @@ export function toApiByteVec(v: Val): string {
82
90
  return Buffer.from(address.slice(1)).toString('hex')
83
91
  }
84
92
  } catch (_) {
85
- return v as string
93
+ throw new Error(`Invalid hex-string: ${v}`)
86
94
  }
87
- return v as string
88
- } else {
89
- throw new Error(`Invalid string: ${v}`)
90
95
  }
96
+ throw new Error(`Invalid hex-string: ${v}`)
91
97
  }
92
98
 
93
99
  export function toApiAddress(v: Val): string {
@@ -99,7 +105,7 @@ export function toApiAddress(v: Val): string {
99
105
  throw new Error(`Invalid base58 string: ${v}`)
100
106
  }
101
107
  } else {
102
- throw new Error(`Invalid string: ${v}`)
108
+ throw new Error(`Invalid value: ${v}, expected a base58 string`)
103
109
  }
104
110
  }
105
111
 
package/src/api/utils.ts CHANGED
@@ -17,6 +17,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
19
  import 'cross-fetch/polyfill'
20
+ import { node } from '..'
20
21
 
21
22
  export function convertHttpResponse<T>(response: { status: number; data: T; error?: { detail: string } }): T {
22
23
  if (response.error) {
@@ -26,3 +27,27 @@ export function convertHttpResponse<T>(response: { status: number; data: T; erro
26
27
  return response.data
27
28
  }
28
29
  }
30
+
31
+ export function isBalanceEqual(b0: node.Balance, b1: node.Balance): boolean {
32
+ const isTokenBalanceEqual = (tokens0?: node.Token[], tokens1?: node.Token[]): boolean => {
33
+ const tokens0Size = tokens0?.length ?? 0
34
+ const tokens1Size = tokens1?.length ?? 0
35
+ if (tokens0Size !== tokens1Size) return false
36
+ if (tokens0Size === 0) return true
37
+ const _tokens1 = tokens1!.map((t) => ({ ...t, used: false }))
38
+ return tokens0!.every((t0) => {
39
+ const t1 = _tokens1.find((t) => !t.used && t0.id === t.id && t0.amount === t.amount)
40
+ if (t1 === undefined) return false
41
+ t1.used = true
42
+ return true
43
+ })
44
+ }
45
+
46
+ const isAlphBalanceEqual = b0.balance === b1.balance && b0.lockedBalance === b1.lockedBalance
47
+ return (
48
+ b0.utxoNum === b1.utxoNum &&
49
+ isAlphBalanceEqual &&
50
+ isTokenBalanceEqual(b0.tokenBalances, b1.tokenBalances) &&
51
+ isTokenBalanceEqual(b0.lockedTokenBalances, b1.lockedTokenBalances)
52
+ )
53
+ }
@@ -1040,7 +1040,11 @@ export class Contract extends Artifact {
1040
1040
  }
1041
1041
 
1042
1042
  buildByteCodeToDeploy(initialFields: Fields): string {
1043
- return ralph.buildContractByteCode(this.bytecode, initialFields, this.fieldsSig)
1043
+ try {
1044
+ return ralph.buildContractByteCode(this.bytecode, initialFields, this.fieldsSig)
1045
+ } catch (error) {
1046
+ throw new Error(`Failed to build bytecode for contract ${this.name}, error: ${error}`)
1047
+ }
1044
1048
  }
1045
1049
 
1046
1050
  static fromApiEvents(
@@ -1186,7 +1190,11 @@ export class Script extends Artifact {
1186
1190
  }
1187
1191
 
1188
1192
  buildByteCodeToDeploy(initialFields: Fields): string {
1189
- return ralph.buildScriptByteCode(this.bytecodeTemplate, initialFields, this.fieldsSig)
1193
+ try {
1194
+ return ralph.buildScriptByteCode(this.bytecodeTemplate, initialFields, this.fieldsSig)
1195
+ } catch (error) {
1196
+ throw new Error(`Failed to build bytecode for script ${this.name}, error: ${error}`)
1197
+ }
1190
1198
  }
1191
1199
  }
1192
1200
 
@@ -17,7 +17,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
19
  import { Buffer } from 'buffer/'
20
- import { Val } from '../api'
20
+ import { Val, toApiAddress, toApiBoolean, toApiByteVec, toApiNumber256 } from '../api'
21
21
  import { bs58, isHexString } from '../utils'
22
22
  import { Fields, FieldsSig } from './contract'
23
23
 
@@ -197,38 +197,24 @@ export function encodeScriptFieldAsString(tpe: string, value: Val): string {
197
197
  return Buffer.from(encodeScriptField(tpe, value)).toString('hex')
198
198
  }
199
199
 
200
+ // TODO: support array type
200
201
  export function encodeScriptField(tpe: string, value: Val): Uint8Array {
201
202
  switch (tpe) {
202
203
  case 'Bool':
203
- if (typeof value === 'boolean') {
204
- const byte = value ? Instruction.trueConst : Instruction.falseConst
205
- return new Uint8Array([byte])
206
- }
207
- break
204
+ const byte = toApiBoolean(value) ? Instruction.trueConst : Instruction.falseConst
205
+ return new Uint8Array([byte])
208
206
  case 'I256':
209
- if (typeof value === 'number' && Number.isInteger(value)) {
210
- return encodeScriptFieldI256(BigInt(value))
211
- } else if (typeof value === 'bigint') {
212
- return encodeScriptFieldI256(value)
213
- }
214
- break
207
+ const i256 = toApiNumber256(value)
208
+ return encodeScriptFieldI256(BigInt(i256))
215
209
  case 'U256':
216
- if (typeof value === 'number' && Number.isInteger(value)) {
217
- return encodeScriptFieldU256(BigInt(value))
218
- } else if (typeof value === 'bigint') {
219
- return encodeScriptFieldU256(value)
220
- }
221
- break
210
+ const u256 = toApiNumber256(value)
211
+ return encodeScriptFieldU256(BigInt(u256))
222
212
  case 'ByteVec':
223
- if (typeof value === 'string') {
224
- return new Uint8Array([Instruction.bytesConst, ...encodeByteVec(value)])
225
- }
226
- break
213
+ const hexStr = toApiByteVec(value)
214
+ return new Uint8Array([Instruction.bytesConst, ...encodeByteVec(hexStr)])
227
215
  case 'Address':
228
- if (typeof value === 'string') {
229
- return new Uint8Array([Instruction.addressConst, ...encodeAddress(value)])
230
- }
231
- break
216
+ const address = toApiAddress(value)
217
+ return new Uint8Array([Instruction.addressConst, ...encodeAddress(address)])
232
218
  }
233
219
 
234
220
  throw invalidScriptField(tpe, value)
@@ -242,13 +228,24 @@ export function buildScriptByteCode(bytecodeTemplate: string, fields: Fields, fi
242
228
  const fieldType = fieldsSig.types[`${fieldIndex}`]
243
229
  if (fieldName in fields) {
244
230
  const fieldValue = fields[`${fieldName}`]
245
- return encodeScriptFieldAsString(fieldType, fieldValue)
231
+ return _encodeField(fieldName, () => encodeScriptFieldAsString(fieldType, fieldValue))
246
232
  } else {
247
233
  throw new Error(`The value of field ${fieldName} is not provided`)
248
234
  }
249
235
  })
250
236
  }
251
237
 
238
+ function _encodeField<T>(fieldName: string, encodeFunc: () => T): T {
239
+ try {
240
+ return encodeFunc()
241
+ } catch (error) {
242
+ if (error instanceof Error) {
243
+ throw new Error(`Invalid ${fieldName}, error: ${error.message}`)
244
+ }
245
+ throw error
246
+ }
247
+ }
248
+
252
249
  function encodeFields(fields: Fields, fieldsSig: FieldsSig, mutable: boolean) {
253
250
  const fieldIndexes = fieldsSig.isMutable
254
251
  .map((_, index) => index)
@@ -258,7 +255,7 @@ function encodeFields(fields: Fields, fieldsSig: FieldsSig, mutable: boolean) {
258
255
  const fieldType = fieldsSig.types[`${fieldIndex}`]
259
256
  if (fieldName in fields) {
260
257
  const fieldValue = fields[`${fieldName}`]
261
- return encodeContractField(fieldType, fieldValue)
258
+ return _encodeField(fieldName, () => encodeContractField(fieldType, fieldValue))
262
259
  } else {
263
260
  throw new Error(`The value of field ${fieldName} is not provided`)
264
261
  }
@@ -311,46 +308,25 @@ function encodeContractFieldArray(tpe: string, val: Val): Uint8Array[] {
311
308
  export function encodeContractField(tpe: string, value: Val): Uint8Array[] {
312
309
  switch (tpe) {
313
310
  case 'Bool':
314
- if (typeof value === 'boolean') {
315
- const byte = value ? 1 : 0
316
- return [new Uint8Array([ApiValType.Bool, byte])]
317
- }
318
- break
311
+ const byte = toApiBoolean(value) ? 1 : 0
312
+ return [new Uint8Array([ApiValType.Bool, byte])]
319
313
  case 'I256':
320
- if (typeof value === 'number' && Number.isInteger(value)) {
321
- return [encodeContractFieldI256(BigInt(value))]
322
- } else if (typeof value === 'bigint') {
323
- return [encodeContractFieldI256(value)]
324
- }
325
- break
314
+ const i256 = toApiNumber256(value)
315
+ return [encodeContractFieldI256(BigInt(i256))]
326
316
  case 'U256':
327
- if (typeof value === 'number' && Number.isInteger(value)) {
328
- return [encodeContractFieldU256(BigInt(value))]
329
- } else if (typeof value === 'bigint') {
330
- return [encodeContractFieldU256(value)]
331
- }
332
- break
317
+ const u256 = toApiNumber256(value)
318
+ return [encodeContractFieldU256(BigInt(u256))]
333
319
  case 'ByteVec':
334
- if (typeof value === 'string') {
335
- return [new Uint8Array([ApiValType.ByteVec, ...encodeByteVec(value)])]
336
- }
337
- break
320
+ const hexStr = toApiByteVec(value)
321
+ return [new Uint8Array([ApiValType.ByteVec, ...encodeByteVec(hexStr)])]
338
322
  case 'Address':
339
- if (typeof value === 'string') {
340
- return [new Uint8Array([ApiValType.Address, ...encodeAddress(value)])]
341
- }
342
- break
323
+ const address = toApiAddress(value)
324
+ return [new Uint8Array([ApiValType.Address, ...encodeAddress(address)])]
343
325
 
344
326
  default:
345
327
  // Array type
346
328
  return encodeContractFieldArray(tpe, value)
347
329
  }
348
-
349
- throw invalidVal(tpe, value)
350
- }
351
-
352
- function invalidVal(tpe: string, value: Val): Error {
353
- return Error(`Invalid API value ${value} for type ${tpe}`)
354
330
  }
355
331
 
356
332
  export function buildDebugBytecode(bytecode: string, bytecodePatch: string): string {