@alephium/web3 1.7.2 → 1.7.4

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.
@@ -21,11 +21,12 @@ import BN from 'bn.js'
21
21
  import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
22
22
  import blake from 'blakejs'
23
23
  import bs58 from '../utils/bs58'
24
- import djb2 from '../utils/djb2'
25
- import { binToHex, concatBytes, hexToBinUnsafe, isHexString } from '../utils'
24
+ import { binToHex, concatBytes, hexToBinUnsafe, isHexString, xorByte } from '../utils'
26
25
  import { KeyType } from '../signer'
27
26
  import { P2MPKH, lockupScriptCodec } from '../codec/lockup-script-codec'
28
27
  import { i32Codec } from '../codec'
28
+ import { LockupScript } from '../codec/lockup-script-codec'
29
+ import djb2 from '../utils/djb2'
29
30
 
30
31
  const ec = new EC('secp256k1')
31
32
  const PublicKeyHashSize = 32
@@ -112,26 +113,19 @@ export function groupOfAddress(address: string): number {
112
113
  }
113
114
  }
114
115
 
115
- function groupOfAddressBytes(bytes: Uint8Array): number {
116
- const hint = djb2(bytes) | 1
117
- const hash = xorByte(hint)
118
- const group = hash % TOTAL_NUMBER_OF_GROUPS
119
- return group
120
- }
121
-
122
116
  // Pay to public key hash address
123
117
  function groupOfP2pkhAddress(address: Uint8Array): number {
124
- return groupOfAddressBytes(address)
118
+ return groupFromBytesForAssetAddress(address)
125
119
  }
126
120
 
127
121
  // Pay to multiple public key hash address
128
122
  function groupOfP2mpkhAddress(address: Uint8Array): number {
129
- return groupOfAddressBytes(address.slice(1, 33))
123
+ return groupFromBytesForAssetAddress(address.slice(1, 33))
130
124
  }
131
125
 
132
126
  // Pay to script hash address
133
127
  function groupOfP2shAddress(address: Uint8Array): number {
134
- return groupOfAddressBytes(address)
128
+ return groupFromBytesForAssetAddress(address)
135
129
  }
136
130
 
137
131
  export function contractIdFromAddress(address: string): Uint8Array {
@@ -225,10 +219,22 @@ export function subContractId(parentContractId: string, pathInHex: string, group
225
219
  return binToHex(bytes)
226
220
  }
227
221
 
228
- export function xorByte(intValue: number): number {
229
- const byte0 = (intValue >> 24) & 0xff
230
- const byte1 = (intValue >> 16) & 0xff
231
- const byte2 = (intValue >> 8) & 0xff
232
- const byte3 = intValue & 0xff
233
- return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff
222
+ export function groupOfLockupScript(lockupScript: LockupScript): number {
223
+ if (lockupScript.kind === 'P2PKH') {
224
+ return groupFromBytesForAssetAddress(lockupScript.value)
225
+ } else if (lockupScript.kind === 'P2MPKH') {
226
+ return groupFromBytesForAssetAddress(lockupScript.value.publicKeyHashes[0])
227
+ } else if (lockupScript.kind === 'P2SH') {
228
+ return groupFromBytesForAssetAddress(lockupScript.value)
229
+ } else {
230
+ // P2C
231
+ const contractId = lockupScript.value
232
+ return contractId[`${contractId.length - 1}`]
233
+ }
234
+ }
235
+
236
+ function groupFromBytesForAssetAddress(bytes: Uint8Array): number {
237
+ const hint = djb2(bytes) | 1
238
+ const hash = xorByte(hint)
239
+ return hash % TOTAL_NUMBER_OF_GROUPS
234
240
  }
@@ -926,6 +926,97 @@ export interface RevealMnemonicResult {
926
926
  mnemonic: string
927
927
  }
928
928
 
929
+ /** RichAssetInput */
930
+ export interface RichAssetInput {
931
+ /** @format int32 */
932
+ hint: number
933
+ /** @format 32-byte-hash */
934
+ key: string
935
+ /** @format hex-string */
936
+ unlockScript: string
937
+ /** @format uint256 */
938
+ attoAlphAmount: string
939
+ /** @format address */
940
+ address: string
941
+ tokens: Token[]
942
+ }
943
+
944
+ /** RichBlockAndEvents */
945
+ export interface RichBlockAndEvents {
946
+ block: RichBlockEntry
947
+ events: ContractEventByBlockHash[]
948
+ }
949
+
950
+ /** RichBlockEntry */
951
+ export interface RichBlockEntry {
952
+ /** @format block-hash */
953
+ hash: string
954
+ /** @format int64 */
955
+ timestamp: number
956
+ /** @format int32 */
957
+ chainFrom: number
958
+ /** @format int32 */
959
+ chainTo: number
960
+ /** @format int32 */
961
+ height: number
962
+ deps: string[]
963
+ transactions: RichTransaction[]
964
+ /** @format hex-string */
965
+ nonce: string
966
+ version: number
967
+ /** @format 32-byte-hash */
968
+ depStateHash: string
969
+ /** @format 32-byte-hash */
970
+ txsHash: string
971
+ /** @format hex-string */
972
+ target: string
973
+ ghostUncles: GhostUncleBlockEntry[]
974
+ }
975
+
976
+ /** RichBlocksAndEventsPerTimeStampRange */
977
+ export interface RichBlocksAndEventsPerTimeStampRange {
978
+ blocksAndEvents: RichBlockAndEvents[][]
979
+ }
980
+
981
+ /** RichContractInput */
982
+ export interface RichContractInput {
983
+ /** @format int32 */
984
+ hint: number
985
+ /** @format 32-byte-hash */
986
+ key: string
987
+ /** @format uint256 */
988
+ attoAlphAmount: string
989
+ /** @format address */
990
+ address: string
991
+ tokens: Token[]
992
+ }
993
+
994
+ /** RichTransaction */
995
+ export interface RichTransaction {
996
+ unsigned: RichUnsignedTx
997
+ scriptExecutionOk: boolean
998
+ contractInputs: RichContractInput[]
999
+ generatedOutputs: Output[]
1000
+ inputSignatures: string[]
1001
+ scriptSignatures: string[]
1002
+ }
1003
+
1004
+ /** RichUnsignedTx */
1005
+ export interface RichUnsignedTx {
1006
+ /** @format 32-byte-hash */
1007
+ txId: string
1008
+ version: number
1009
+ networkId: number
1010
+ /** @format script */
1011
+ scriptOpt?: string
1012
+ /** @format int32 */
1013
+ gasAmount: number
1014
+ /** @format uint256 */
1015
+ gasPrice: string
1016
+ inputs: RichAssetInput[]
1017
+ fixedOutputs: FixedAssetOutput[]
1018
+ }
1019
+
929
1020
  /** Script */
930
1021
  export interface Script {
931
1022
  code: string
@@ -1512,7 +1603,7 @@ export class HttpClient<SecurityDataType = unknown> {
1512
1603
 
1513
1604
  /**
1514
1605
  * @title Alephium API
1515
- * @version 3.6.2
1606
+ * @version 3.7.0
1516
1607
  * @baseUrl ../
1517
1608
  */
1518
1609
  export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
@@ -2169,6 +2260,40 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
2169
2260
  ...params
2170
2261
  }).then(convertHttpResponse),
2171
2262
 
2263
+ /**
2264
+ * No description
2265
+ *
2266
+ * @tags Blockflow
2267
+ * @name GetBlockflowRichBlocks
2268
+ * @summary Given a time interval, list blocks containing events and transactions with enriched input information when node indexes are enabled.
2269
+ * @request GET:/blockflow/rich-blocks
2270
+ */
2271
+ getBlockflowRichBlocks: (
2272
+ query: {
2273
+ /**
2274
+ * @format int64
2275
+ * @min 0
2276
+ */
2277
+ fromTs: number
2278
+ /**
2279
+ * @format int64
2280
+ * @min 0
2281
+ */
2282
+ toTs?: number
2283
+ },
2284
+ params: RequestParams = {}
2285
+ ) =>
2286
+ this.request<
2287
+ RichBlocksAndEventsPerTimeStampRange,
2288
+ BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable
2289
+ >({
2290
+ path: `/blockflow/rich-blocks`,
2291
+ method: 'GET',
2292
+ query: query,
2293
+ format: 'json',
2294
+ ...params
2295
+ }).then(convertHttpResponse),
2296
+
2172
2297
  /**
2173
2298
  * No description
2174
2299
  *
@@ -2217,6 +2342,24 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
2217
2342
  ...params
2218
2343
  }).then(convertHttpResponse),
2219
2344
 
2345
+ /**
2346
+ * No description
2347
+ *
2348
+ * @tags Blockflow
2349
+ * @name GetBlockflowRichBlocksBlockHash
2350
+ * @summary Get a block containing events and transactions with enriched input information when node indexes are enabled.
2351
+ * @request GET:/blockflow/rich-blocks/{block_hash}
2352
+ */
2353
+ getBlockflowRichBlocksBlockHash: (blockHash: string, params: RequestParams = {}) =>
2354
+ this.request<RichBlockAndEvents, BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>(
2355
+ {
2356
+ path: `/blockflow/rich-blocks/${blockHash}`,
2357
+ method: 'GET',
2358
+ format: 'json',
2359
+ ...params
2360
+ }
2361
+ ).then(convertHttpResponse),
2362
+
2220
2363
  /**
2221
2364
  * No description
2222
2365
  *
@@ -190,6 +190,7 @@ export interface AssetOutput {
190
190
 
191
191
  /** NFT */
192
192
  export interface NFT {
193
+ id: string
193
194
  type: string
194
195
  }
195
196
 
@@ -217,6 +218,14 @@ export interface AcceptedTransaction {
217
218
  timestamp: number
218
219
  }
219
220
 
221
+ /** HolderInfo */
222
+ export interface HolderInfo {
223
+ /** @format address */
224
+ address: string
225
+ /** @format uint256 */
226
+ balance: string
227
+ }
228
+
220
229
  /** TokenSupply */
221
230
  export interface TokenSupply {
222
231
  /** @format uint256 */
@@ -317,6 +326,8 @@ export enum TokenStdInterfaceId {
317
326
  export interface ExplorerInfo {
318
327
  releaseVersion: string
319
328
  commit: string
329
+ /** @format int64 */
330
+ lastHoldersUpdate: number
320
331
  /** @format int32 */
321
332
  migrationsVersion: number
322
333
  /** @format int64 */
@@ -367,6 +378,7 @@ export interface Transaction {
367
378
 
368
379
  /** FungibleToken */
369
380
  export interface FungibleToken {
381
+ id: string
370
382
  type: string
371
383
  }
372
384
 
@@ -1588,6 +1600,40 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1588
1600
  ...params
1589
1601
  }).then(convertHttpResponse),
1590
1602
 
1603
+ /**
1604
+ * @description Get a sorted list of top addresses by {token_id} balance. Updates once per day.
1605
+ *
1606
+ * @tags Tokens
1607
+ * @name GetTokensHoldersTokenTokenId
1608
+ * @request GET:/tokens/holders/token/{token_id}
1609
+ */
1610
+ getTokensHoldersTokenTokenId: (
1611
+ tokenId: string,
1612
+ query?: {
1613
+ /**
1614
+ * Page number
1615
+ * @format int32
1616
+ * @min 1
1617
+ */
1618
+ page?: number
1619
+ /**
1620
+ * Number of items per page
1621
+ * @format int32
1622
+ * @min 0
1623
+ * @max 100
1624
+ */
1625
+ limit?: number
1626
+ },
1627
+ params: RequestParams = {}
1628
+ ) =>
1629
+ this.request<HolderInfo[], BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
1630
+ path: `/tokens/holders/token/${tokenId}`,
1631
+ method: 'GET',
1632
+ query: query,
1633
+ format: 'json',
1634
+ ...params
1635
+ }).then(convertHttpResponse),
1636
+
1591
1637
  /**
1592
1638
  * @description List token transactions
1593
1639
  *
@@ -1676,6 +1722,39 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1676
1722
  ...params
1677
1723
  }).then(convertHttpResponse),
1678
1724
 
1725
+ /**
1726
+ * @description Get a sorted list of top addresses by ALPH balance. Updates once per day.
1727
+ *
1728
+ * @tags Tokens
1729
+ * @name GetTokensHoldersAlph
1730
+ * @request GET:/tokens/holders/alph
1731
+ */
1732
+ getTokensHoldersAlph: (
1733
+ query?: {
1734
+ /**
1735
+ * Page number
1736
+ * @format int32
1737
+ * @min 1
1738
+ */
1739
+ page?: number
1740
+ /**
1741
+ * Number of items per page
1742
+ * @format int32
1743
+ * @min 0
1744
+ * @max 100
1745
+ */
1746
+ limit?: number
1747
+ },
1748
+ params: RequestParams = {}
1749
+ ) =>
1750
+ this.request<HolderInfo[], BadRequest | Unauthorized | NotFound | InternalServerError | ServiceUnavailable>({
1751
+ path: `/tokens/holders/alph`,
1752
+ method: 'GET',
1753
+ query: query,
1754
+ format: 'json',
1755
+ ...params
1756
+ }).then(convertHttpResponse),
1757
+
1679
1758
  /**
1680
1759
  * @description Return metadata for the given nft tokens, if metadata doesn't exist or token isn't a nft, it won't be in the output list
1681
1760
  *
@@ -2046,12 +2046,14 @@ function toFieldsSig(contractName: string, functionSig: FunctionSig): FieldsSig
2046
2046
  }
2047
2047
  }
2048
2048
 
2049
+ type Calls = Record<string, Optional<CallContractParams<any>, 'args'>>
2049
2050
  export async function multicallMethods<I extends ContractInstance, F extends Fields>(
2050
2051
  contract: ContractFactory<I, F>,
2051
2052
  instance: ContractInstance,
2052
- callss: Record<string, Optional<CallContractParams<any>, 'args'>>[],
2053
+ _callss: Calls | Calls[],
2053
2054
  getContractByCodeHash: (codeHash: string) => Contract
2054
2055
  ): Promise<Record<string, CallContractResult<any>>[] | Record<string, CallContractResult<any>>> {
2056
+ const callss = Array.isArray(_callss) ? _callss : [_callss]
2055
2057
  const callEntries = callss.map((calls) => Object.entries(calls))
2056
2058
  const callsParams = callEntries.map((entries) => {
2057
2059
  return entries.map((entry) => {
@@ -2068,7 +2070,7 @@ export async function multicallMethods<I extends ContractInstance, F extends Fie
2068
2070
  })
2069
2071
  const result = await getCurrentNodeProvider().contracts.postContractsMulticallContract({ calls: callsParams.flat() })
2070
2072
  let callResultIndex = 0
2071
- return callsParams.map((calls, index0) => {
2073
+ const results = callsParams.map((calls, index0) => {
2072
2074
  const callsResult: Record<string, CallContractResult<any>> = {}
2073
2075
  const entries = callEntries[`${index0}`]
2074
2076
  calls.forEach((call, index1) => {
@@ -2085,6 +2087,7 @@ export async function multicallMethods<I extends ContractInstance, F extends Fie
2085
2087
  })
2086
2088
  return callsResult
2087
2089
  })
2090
+ return Array.isArray(_callss) ? results : results[0]
2088
2091
  }
2089
2092
 
2090
2093
  export async function getContractEventsCurrentCount(contractAddress: Address): Promise<number> {
@@ -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 { binToHex } from '../utils'
19
+ import { binToHex, hexToBinUnsafe } from '../utils'
20
20
  import { fromApiNumber256, node, NodeProvider, toApiNumber256Optional, toApiTokens } from '../api'
21
21
  import { addressFromPublicKey, contractIdFromAddress } from '../address'
22
22
  import { toApiDestinations } from './signer'
@@ -32,6 +32,9 @@ import {
32
32
  SignUnsignedTxParams,
33
33
  SignUnsignedTxResult
34
34
  } from './types'
35
+ import { unsignedTxCodec, UnsignedTxCodec } from '../codec'
36
+ import { groupIndexOfTransaction } from '../transaction'
37
+ import { blakeHash } from '../codec/hash'
35
38
 
36
39
  export abstract class TransactionBuilder {
37
40
  abstract get nodeProvider(): NodeProvider
@@ -113,16 +116,18 @@ export abstract class TransactionBuilder {
113
116
  return { ...response, groupIndex: response.fromGroup, gasPrice: fromApiNumber256(response.gasPrice) }
114
117
  }
115
118
 
116
- async buildUnsignedTx(params: SignUnsignedTxParams): Promise<Omit<SignUnsignedTxResult, 'signature'>> {
117
- const data = { unsignedTx: params.unsignedTx }
118
- const decoded = await this.nodeProvider.transactions.postTransactionsDecodeUnsignedTx(data)
119
+ buildUnsignedTx(params: SignUnsignedTxParams): Omit<SignUnsignedTxResult, 'signature'> {
120
+ const unsignedTxBin = hexToBinUnsafe(params.unsignedTx)
121
+ const decoded = unsignedTxCodec.decode(unsignedTxBin)
122
+ const txId = binToHex(blakeHash(unsignedTxBin))
123
+ const [fromGroup, toGroup] = groupIndexOfTransaction(decoded)
119
124
  return {
120
- fromGroup: decoded.fromGroup,
121
- toGroup: decoded.toGroup,
125
+ fromGroup: fromGroup,
126
+ toGroup: toGroup,
122
127
  unsignedTx: params.unsignedTx,
123
- txId: decoded.unsignedTx.txId,
124
- gasAmount: decoded.unsignedTx.gasAmount,
125
- gasPrice: fromApiNumber256(decoded.unsignedTx.gasPrice)
128
+ txId: txId,
129
+ gasAmount: decoded.gasAmount,
130
+ gasPrice: decoded.gasPrice
126
131
  }
127
132
  }
128
133
  }
@@ -16,8 +16,12 @@ 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 { groupOfLockupScript } from '../address'
19
20
  import { node } from '../api'
21
+ import { UnsignedTx } from '../codec'
22
+ import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
20
23
  import { getCurrentNodeProvider } from '../global'
24
+ import { xorByte } from '../utils'
21
25
 
22
26
  function isConfirmed(txStatus: node.TxStatus): txStatus is node.Confirmed {
23
27
  return txStatus.type === 'Confirmed'
@@ -36,3 +40,25 @@ export async function waitForTxConfirmation(
36
40
  await new Promise((r) => setTimeout(r, requestInterval))
37
41
  return waitForTxConfirmation(txId, confirmations, requestInterval)
38
42
  }
43
+
44
+ export function groupIndexOfTransaction(unsignedTx: UnsignedTx): [number, number] {
45
+ if (unsignedTx.inputs.length === 0) throw new Error('Empty inputs for unsignedTx')
46
+
47
+ const fromGroup = groupFromHint(unsignedTx.inputs[0].hint)
48
+
49
+ let toGroup = fromGroup
50
+ for (const output of unsignedTx.fixedOutputs) {
51
+ const outputGroup = groupOfLockupScript(output.lockupScript)
52
+ if (outputGroup !== fromGroup) {
53
+ toGroup = outputGroup
54
+ break
55
+ }
56
+ }
57
+
58
+ return [fromGroup, toGroup]
59
+ }
60
+
61
+ function groupFromHint(hint: number): number {
62
+ const hash = xorByte(hint)
63
+ return hash % TOTAL_NUMBER_OF_GROUPS
64
+ }
@@ -156,8 +156,24 @@ export function concatBytes(arrays: Uint8Array[]): Uint8Array {
156
156
  return result
157
157
  }
158
158
 
159
+ export function xorByte(intValue: number): number {
160
+ const byte0 = (intValue >> 24) & 0xff
161
+ const byte1 = (intValue >> 16) & 0xff
162
+ const byte2 = (intValue >> 8) & 0xff
163
+ const byte3 = intValue & 0xff
164
+ return (byte0 ^ byte1 ^ byte2 ^ byte3) & 0xff
165
+ }
166
+
159
167
  type _Eq<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false
160
168
  export type Eq<X, Y> = _Eq<{ [P in keyof X]: X[P] }, { [P in keyof Y]: Y[P] }>
161
169
  // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
162
170
  export function assertType<T extends true>(): void {}
163
171
  export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>
172
+
173
+ export type Narrow<type> =
174
+ | (unknown extends type ? unknown : never)
175
+ // eslint-disable-next-line @typescript-eslint/ban-types
176
+ | (type extends Function ? type : never)
177
+ | (type extends bigint | boolean | number | string ? type : never)
178
+ | (type extends [] ? [] : never)
179
+ | { [K in keyof type]: Narrow<type[K]> }