@alephium/web3 0.40.0 → 0.42.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.
Files changed (68) hide show
  1. package/dist/alephium-web3.min.js +1 -1
  2. package/dist/alephium-web3.min.js.map +1 -1
  3. package/dist/src/api/node-provider.d.ts +2 -0
  4. package/dist/src/api/node-provider.js +12 -6
  5. package/dist/src/api/utils.d.ts +1 -1
  6. package/dist/src/block/block.d.ts +28 -0
  7. package/dist/src/block/block.js +131 -0
  8. package/dist/src/block/index.d.ts +1 -0
  9. package/dist/src/block/index.js +22 -0
  10. package/dist/src/codec/contract-output-codec.js +4 -4
  11. package/dist/src/codec/lockup-script-codec.js +2 -2
  12. package/dist/src/codec/method-codec.d.ts +3 -1
  13. package/dist/src/codec/method-codec.js +27 -2
  14. package/dist/src/codec/script-codec.d.ts +11 -6
  15. package/dist/src/codec/script-codec.js +13 -2
  16. package/dist/src/codec/transaction-codec.js +2 -2
  17. package/dist/src/codec/unlock-script-codec.d.ts +2 -2
  18. package/dist/src/codec/unsigned-tx-codec.d.ts +2 -2
  19. package/dist/src/contract/contract.d.ts +23 -101
  20. package/dist/src/contract/contract.js +52 -538
  21. package/dist/src/contract/events.d.ts +1 -2
  22. package/dist/src/contract/events.js +28 -14
  23. package/dist/src/index.d.ts +1 -0
  24. package/dist/src/index.js +1 -0
  25. package/dist/src/signer/tx-builder.js +4 -4
  26. package/dist/src/transaction/index.d.ts +1 -0
  27. package/dist/src/transaction/index.js +1 -0
  28. package/dist/src/transaction/status.js +28 -4
  29. package/dist/src/transaction/utils.d.ts +2 -0
  30. package/dist/src/transaction/utils.js +34 -0
  31. package/dist/src/utils/address.js +29 -16
  32. package/dist/src/utils/exchange.js +25 -15
  33. package/dist/src/utils/number.d.ts +1 -1
  34. package/dist/src/utils/sign.js +6 -6
  35. package/dist/src/utils/subscription.d.ts +4 -4
  36. package/dist/src/utils/subscription.js +1 -1
  37. package/package.json +3 -3
  38. package/src/api/node-provider.ts +8 -1
  39. package/src/api/utils.ts +1 -1
  40. package/src/block/block.ts +139 -0
  41. package/src/block/index.ts +19 -0
  42. package/src/codec/contract-output-codec.ts +1 -1
  43. package/src/codec/lockup-script-codec.ts +3 -3
  44. package/src/codec/method-codec.ts +41 -3
  45. package/src/codec/script-codec.ts +23 -5
  46. package/src/codec/transaction-codec.ts +1 -1
  47. package/src/codec/unlock-script-codec.ts +2 -2
  48. package/src/codec/unsigned-tx-codec.ts +2 -2
  49. package/src/contract/contract.ts +72 -779
  50. package/src/contract/events.ts +6 -18
  51. package/src/index.ts +1 -0
  52. package/src/signer/tx-builder.ts +2 -2
  53. package/src/transaction/index.ts +1 -0
  54. package/src/transaction/status.ts +4 -4
  55. package/src/transaction/utils.ts +38 -0
  56. package/src/utils/address.ts +15 -2
  57. package/src/utils/exchange.ts +32 -10
  58. package/src/utils/number.ts +1 -1
  59. package/src/utils/sign.ts +1 -1
  60. package/src/utils/subscription.ts +4 -4
  61. package/std/fungible_token_interface.ral +1 -0
  62. package/std/nft_collection_interface.ral +1 -0
  63. package/std/nft_collection_with_royalty_interface.ral +1 -0
  64. package/std/nft_interface.ral +1 -0
  65. package/webpack.config.js +0 -1
  66. package/dist/src/utils/error.d.ts +0 -15
  67. package/dist/src/utils/error.js +0 -66
  68. package/src/utils/error.ts +0 -77
@@ -0,0 +1,139 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ import { Subscription, SubscribeOptions } from '../utils/subscription'
20
+ import * as node from '../api/api-alephium'
21
+ import { NodeProvider } from '../api'
22
+ import * as web3 from '../global'
23
+
24
+ export type ReorgCallback = (orphanBlocks: node.BlockEntry[], newBlocks: node.BlockEntry[]) => Promise<void> | void
25
+
26
+ export interface BlockSubscribeOptions extends SubscribeOptions<node.BlockEntry> {
27
+ reorgCallback?: ReorgCallback
28
+ }
29
+
30
+ export abstract class BlockSubscriptionBase extends Subscription<node.BlockEntry> {
31
+ abstract readonly reorgCallback?: ReorgCallback
32
+ abstract readonly fromGroup: number
33
+ abstract readonly toGroup: number
34
+
35
+ abstract getHashesAtHeight(height: number): Promise<string[]>
36
+ abstract getBlockByHash(hash: string): Promise<node.BlockEntry>
37
+
38
+ protected getParentHash(block: node.BlockEntry): string {
39
+ const index = Math.floor(block.deps.length / 2) + this.toGroup
40
+ return block.deps[index]
41
+ }
42
+
43
+ protected async handleReorg(blockHash: string, blockHeight: number) {
44
+ console.info(`reorg occur, hash: ${blockHash}, height: ${blockHeight}`)
45
+ if (this.reorgCallback === undefined) return
46
+
47
+ const orphans: string[] = []
48
+ const newHashes: string[] = []
49
+ let fromHash = blockHash
50
+ let fromHeight = blockHeight
51
+ while (true) {
52
+ const hashes = await this.getHashesAtHeight(fromHeight)
53
+ const canonicalHash = hashes[0]
54
+ if (canonicalHash !== fromHash) {
55
+ orphans.push(fromHash)
56
+ newHashes.push(canonicalHash)
57
+ const block = await this.getBlockByHash(fromHash)
58
+ fromHash = this.getParentHash(block)
59
+ fromHeight -= 1
60
+ } else {
61
+ break
62
+ }
63
+ }
64
+
65
+ const orphanBlocks: node.BlockEntry[] = []
66
+ for (const hash of orphans.reverse()) {
67
+ const block = await this.getBlockByHash(hash)
68
+ orphanBlocks.push(block)
69
+ }
70
+
71
+ const newBlocks: node.BlockEntry[] = []
72
+ for (const hash of newHashes.reverse()) {
73
+ const block = await this.getBlockByHash(hash)
74
+ newBlocks.push(block)
75
+ }
76
+ console.info(`orphan hashes: ${orphanBlocks.map((b) => b.hash)}, new hashes: ${newBlocks.map((b) => b.hash)}`)
77
+ await this.reorgCallback(orphanBlocks, newBlocks)
78
+ }
79
+ }
80
+
81
+ export class BlockSubscription extends BlockSubscriptionBase {
82
+ readonly nodeProvider: NodeProvider
83
+ readonly fromGroup: number
84
+ readonly toGroup: number
85
+ readonly reorgCallback?: ReorgCallback
86
+ private currentBlockHeight: number
87
+ private parentBlockHash: string | undefined
88
+
89
+ constructor(
90
+ options: BlockSubscribeOptions,
91
+ fromGroup: number,
92
+ toGroup: number,
93
+ fromBlockHeight: number,
94
+ nodeProvider: NodeProvider | undefined = undefined
95
+ ) {
96
+ super(options)
97
+ this.nodeProvider = nodeProvider ?? web3.getCurrentNodeProvider()
98
+ this.fromGroup = fromGroup
99
+ this.toGroup = toGroup
100
+ this.reorgCallback = options.reorgCallback
101
+ this.currentBlockHeight = fromBlockHeight
102
+ this.parentBlockHash = undefined
103
+ }
104
+
105
+ override async getHashesAtHeight(height: number): Promise<string[]> {
106
+ const result = await this.nodeProvider.blockflow.getBlockflowHashes({
107
+ fromGroup: this.fromGroup,
108
+ toGroup: this.toGroup,
109
+ height
110
+ })
111
+ return result.headers
112
+ }
113
+
114
+ override async getBlockByHash(hash: string): Promise<node.BlockEntry> {
115
+ return await this.nodeProvider.blockflow.getBlockflowBlocksBlockHash(hash)
116
+ }
117
+
118
+ override async polling(): Promise<void> {
119
+ try {
120
+ const chainInfo = await this.nodeProvider.blockflow.getBlockflowChainInfo({
121
+ fromGroup: this.fromGroup,
122
+ toGroup: this.toGroup
123
+ })
124
+
125
+ while (this.currentBlockHeight <= chainInfo.currentHeight) {
126
+ const hashes = await this.getHashesAtHeight(this.currentBlockHeight)
127
+ const block = await this.getBlockByHash(hashes[0])
128
+ if (this.parentBlockHash !== undefined && this.getParentHash(block) !== this.parentBlockHash) {
129
+ await this.handleReorg(this.parentBlockHash, this.currentBlockHeight - 1)
130
+ }
131
+ await this.messageCallback(block)
132
+ this.currentBlockHeight += 1
133
+ this.parentBlockHash = hashes[0]
134
+ }
135
+ } catch (err) {
136
+ await this.errorCallback(err, this)
137
+ }
138
+ }
139
+ }
@@ -0,0 +1,19 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ export { ReorgCallback, BlockSubscribeOptions, BlockSubscription } from './block'
@@ -24,7 +24,7 @@ import { Codec } from './codec'
24
24
  import { Token, tokensCodec } from './token-codec'
25
25
  import { ContractOutput as ApiContractOutput } from '../api/api-alephium'
26
26
  import { blakeHash, createHint } from './hash'
27
- import { binToHex, bs58 } from '..'
27
+ import { binToHex, bs58 } from '../utils'
28
28
  import { signedIntCodec } from './signed-int-codec'
29
29
  import { lockupScriptCodec } from './lockup-script-codec'
30
30
 
@@ -17,7 +17,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  import { Buffer } from 'buffer/'
19
19
  import { Parser } from 'binary-parser'
20
- import { DecodedCompactInt, compactUnsignedIntCodec } from './compact-int-codec'
20
+ import { DecodedCompactInt, compactSignedIntCodec } from './compact-int-codec'
21
21
  import { Codec } from './codec'
22
22
  import { ArrayCodec, DecodedArray } from './array-codec'
23
23
 
@@ -41,7 +41,7 @@ const publicKeyHashCodec = new PublicKeyHashCodec()
41
41
  const publicKeyHashesCodec = new ArrayCodec(publicKeyHashCodec)
42
42
  const multiSigParser = Parser.start()
43
43
  .nest('publicKeyHashes', { type: publicKeyHashesCodec.parser })
44
- .nest('m', { type: compactUnsignedIntCodec.parser })
44
+ .nest('m', { type: compactSignedIntCodec.parser })
45
45
  export interface MultiSig {
46
46
  publicKeyHashes: DecodedArray<PublicKeyHash>
47
47
  m: DecodedCompactInt
@@ -79,7 +79,7 @@ export class LockupScriptCodec implements Codec<LockupScript> {
79
79
  result.push(...(input.script as PublicKeyHash).publicKeyHash)
80
80
  } else if (input.scriptType === 1) {
81
81
  result.push(...publicKeyHashesCodec.encode((input.script as MultiSig).publicKeyHashes.value))
82
- result.push(...compactUnsignedIntCodec.encode((input.script as MultiSig).m))
82
+ result.push(...compactSignedIntCodec.encode((input.script as MultiSig).m))
83
83
  } else if (input.scriptType === 2) {
84
84
  result.push(...(input.script as P2SH).scriptHash)
85
85
  } else if (input.scriptType === 3) {
@@ -33,13 +33,51 @@ export interface DecodedMethod {
33
33
 
34
34
  export interface Method {
35
35
  isPublic: boolean
36
- assetModifier: number
36
+ usePreapprovedAssets: boolean
37
+ useContractAssets: boolean
38
+ usePayToContractOnly: boolean
37
39
  argsLength: number
38
40
  localsLength: number
39
41
  returnLength: number
40
42
  instrs: Instr[]
41
43
  }
42
44
 
45
+ function decodeAssetModifier(encoded: number): {
46
+ usePreapprovedAssets: boolean
47
+ useContractAssets: boolean
48
+ usePayToContractOnly: boolean
49
+ } {
50
+ const usePayToContractOnly = (encoded & 4) !== 0
51
+ switch (encoded & 3) {
52
+ case 0:
53
+ return { usePayToContractOnly, usePreapprovedAssets: false, useContractAssets: false }
54
+ case 1:
55
+ return { usePayToContractOnly, usePreapprovedAssets: true, useContractAssets: true }
56
+ case 2:
57
+ return { usePayToContractOnly, usePreapprovedAssets: false, useContractAssets: true }
58
+ case 3:
59
+ return { usePayToContractOnly, usePreapprovedAssets: true, useContractAssets: false }
60
+ default:
61
+ throw new Error(`Invalid asset modifier: ${encoded}`)
62
+ }
63
+ }
64
+
65
+ function encodeAssetModifier(arg: {
66
+ usePreapprovedAssets: boolean
67
+ useContractAssets: boolean
68
+ usePayToContractOnly: boolean
69
+ }): number {
70
+ const encoded =
71
+ !arg.usePreapprovedAssets && !arg.useContractAssets
72
+ ? 0
73
+ : arg.usePreapprovedAssets && arg.useContractAssets
74
+ ? 1
75
+ : !arg.usePreapprovedAssets && arg.useContractAssets
76
+ ? 2
77
+ : 3
78
+ return encoded | (arg.usePayToContractOnly ? 4 : 0)
79
+ }
80
+
43
81
  export class MethodCodec implements Codec<DecodedMethod> {
44
82
  parser = Parser.start()
45
83
  .uint8('isPublic')
@@ -73,7 +111,7 @@ export class MethodCodec implements Codec<DecodedMethod> {
73
111
  static toMethod(decodedMethod: DecodedMethod): Method {
74
112
  return {
75
113
  isPublic: decodedMethod.isPublic === 1,
76
- assetModifier: decodedMethod.assetModifier,
114
+ ...decodeAssetModifier(decodedMethod.assetModifier),
77
115
  argsLength: compactUnsignedIntCodec.toU32(decodedMethod.argsLength),
78
116
  localsLength: compactUnsignedIntCodec.toU32(decodedMethod.localsLength),
79
117
  returnLength: compactUnsignedIntCodec.toU32(decodedMethod.returnLength),
@@ -84,7 +122,7 @@ export class MethodCodec implements Codec<DecodedMethod> {
84
122
  static fromMethod(method: Method): DecodedMethod {
85
123
  return {
86
124
  isPublic: method.isPublic ? 1 : 0,
87
- assetModifier: method.assetModifier,
125
+ assetModifier: encodeAssetModifier(method),
88
126
  argsLength: compactUnsignedIntCodec.fromU32(method.argsLength),
89
127
  localsLength: compactUnsignedIntCodec.fromU32(method.localsLength),
90
128
  returnLength: compactUnsignedIntCodec.fromU32(method.returnLength),
@@ -15,30 +15,48 @@ GNU Lesser General Public License for more details.
15
15
  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 { Buffer } from 'buffer/'
19
20
  import { Parser } from 'binary-parser'
20
21
  import { DecodedArray } from './array-codec'
21
22
  import { Codec } from './codec'
22
- import { DecodedMethod, methodsCodec } from './method-codec'
23
+ import { DecodedMethod, methodsCodec, Method, MethodCodec } from './method-codec'
23
24
  import { OptionCodec } from './option-codec'
25
+ import { compactUnsignedIntCodec } from './compact-int-codec'
24
26
 
25
- export interface Script {
27
+ export interface DecodedScript {
26
28
  methods: DecodedArray<DecodedMethod>
27
29
  }
28
30
 
29
- export class ScriptCodec implements Codec<Script> {
31
+ export interface Script {
32
+ methods: Method[]
33
+ }
34
+
35
+ export class ScriptCodec implements Codec<DecodedScript> {
30
36
  parser = Parser.start().nest('methods', {
31
37
  type: methodsCodec.parser
32
38
  })
33
39
 
34
- encode(input: Script): Buffer {
40
+ encode(input: DecodedScript): Buffer {
35
41
  const script = methodsCodec.encode(input.methods.value)
36
42
  return Buffer.from(script)
37
43
  }
38
44
 
39
- decode(input: Buffer): Script {
45
+ decode(input: Buffer): DecodedScript {
40
46
  return this.parser.parse(input)
41
47
  }
48
+
49
+ decodeScript(input: Buffer): Script {
50
+ const decodedTxScript = this.decode(input)
51
+ const methods = decodedTxScript.methods.value.map((decodedMethod) => MethodCodec.toMethod(decodedMethod))
52
+ return { methods }
53
+ }
54
+
55
+ encodeScript(inputTxScript: Script): Buffer {
56
+ const methodLength = compactUnsignedIntCodec.fromU32(inputTxScript.methods.length)
57
+ const decodedMethods = inputTxScript.methods.map((method) => MethodCodec.fromMethod(method))
58
+ return this.encode({ methods: { value: decodedMethods, length: methodLength } })
59
+ }
42
60
  }
43
61
 
44
62
  export const scriptCodec = new ScriptCodec()
@@ -27,7 +27,7 @@ import { Either } from './either-codec'
27
27
  import { AssetOutput, AssetOutputCodec } from './asset-output-codec'
28
28
  import { ContractOutput, ContractOutputCodec } from './contract-output-codec'
29
29
  import { FixedAssetOutput, Transaction as ApiTransaction } from '../api/api-alephium'
30
- import { hexToBinUnsafe } from '..'
30
+ import { hexToBinUnsafe } from '../utils'
31
31
  import { ContractOutput as ApiContractOutput } from '../api/api-alephium'
32
32
  import { Codec } from './codec'
33
33
  import { Output, outputCodec, outputsCodec } from './output-codec'
@@ -20,7 +20,7 @@ import { Parser } from 'binary-parser'
20
20
  import { ArrayCodec, DecodedArray } from './array-codec'
21
21
  import { compactUnsignedIntCodec, compactSignedIntCodec, DecodedCompactInt } from './compact-int-codec'
22
22
  import { Codec } from './codec'
23
- import { Script, scriptCodec } from './script-codec'
23
+ import { DecodedScript, Script, scriptCodec } from './script-codec'
24
24
  import { ByteString, byteStringCodec } from './bytestring-codec'
25
25
  import { LockupScript, lockupScriptCodec } from './lockup-script-codec'
26
26
 
@@ -122,7 +122,7 @@ const valCodec = new ValCodec()
122
122
  const valsCodec = new ArrayCodec(valCodec)
123
123
 
124
124
  export interface P2SH {
125
- script: Script
125
+ script: DecodedScript
126
126
  params: DecodedArray<Val>
127
127
  }
128
128
 
@@ -19,7 +19,7 @@ import { Buffer } from 'buffer/'
19
19
  import { Parser } from 'binary-parser'
20
20
  import { UnsignedTx as ApiUnsignedTx } from '../api/api-alephium'
21
21
  import { binToHex, hexToBinUnsafe } from '../utils'
22
- import { Script, scriptCodec, statefulScriptCodecOpt } from './script-codec'
22
+ import { DecodedScript, scriptCodec, statefulScriptCodecOpt } from './script-codec'
23
23
  import { Option } from './option-codec'
24
24
  import { DecodedCompactInt, compactSignedIntCodec, compactUnsignedIntCodec } from './compact-int-codec'
25
25
  import { Input, InputCodec, inputsCodec } from './input-codec'
@@ -31,7 +31,7 @@ import { Codec } from './codec'
31
31
  export interface UnsignedTx {
32
32
  version: number
33
33
  networkId: number
34
- statefulScript: Option<Script>
34
+ statefulScript: Option<DecodedScript>
35
35
  gasAmount: DecodedCompactInt
36
36
  gasPrice: DecodedCompactInt
37
37
  inputs: DecodedArray<Input>