@alephium/web3 0.2.0-test.0 → 0.2.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 (126) hide show
  1. package/.eslintignore +2 -2
  2. package/README.md +2 -135
  3. package/dist/alephium-web3.min.js +1 -1
  4. package/dist/alephium-web3.min.js.LICENSE.txt +0 -17
  5. package/dist/alephium-web3.min.js.map +1 -1
  6. package/dist/src/api/api-alephium.d.ts +152 -24
  7. package/dist/src/api/api-alephium.js +163 -82
  8. package/dist/src/api/api-explorer.d.ts +192 -49
  9. package/dist/src/api/api-explorer.js +195 -34
  10. package/dist/src/api/index.d.ts +40 -5
  11. package/dist/src/api/index.js +115 -7
  12. package/dist/src/api/types.d.ts +23 -0
  13. package/dist/src/api/types.js +235 -0
  14. package/dist/src/api/utils.d.ts +6 -0
  15. package/dist/{scripts/rename-gitignore.js → src/api/utils.js} +11 -6
  16. package/dist/src/contract/contract.d.ts +127 -80
  17. package/dist/src/contract/contract.js +425 -467
  18. package/dist/src/contract/events.d.ts +4 -4
  19. package/dist/src/contract/events.js +2 -1
  20. package/dist/src/contract/index.js +5 -1
  21. package/dist/src/contract/ralph.d.ts +5 -4
  22. package/dist/src/contract/ralph.js +27 -1
  23. package/dist/src/global.d.ts +7 -0
  24. package/dist/src/global.js +54 -0
  25. package/dist/src/index.d.ts +2 -0
  26. package/dist/src/index.js +23 -1
  27. package/dist/src/signer/index.d.ts +0 -1
  28. package/dist/src/signer/index.js +5 -2
  29. package/dist/src/signer/signer.d.ts +59 -60
  30. package/dist/src/signer/signer.js +99 -69
  31. package/dist/src/transaction/index.d.ts +0 -1
  32. package/dist/src/transaction/index.js +5 -2
  33. package/dist/src/transaction/status.d.ts +2 -1
  34. package/dist/src/transaction/status.js +2 -1
  35. package/dist/src/utils/bs58.d.ts +1 -0
  36. package/dist/src/utils/bs58.js +13 -1
  37. package/dist/src/utils/index.d.ts +0 -1
  38. package/dist/src/utils/index.js +5 -2
  39. package/dist/src/utils/subscription.d.ts +0 -3
  40. package/dist/src/utils/subscription.js +0 -1
  41. package/dist/src/utils/utils.d.ts +6 -11
  42. package/dist/src/utils/utils.js +22 -26
  43. package/jest-config.json +11 -0
  44. package/package.json +11 -47
  45. package/src/api/api-alephium.ts +219 -33
  46. package/src/api/api-explorer.ts +275 -52
  47. package/src/api/index.ts +140 -6
  48. package/src/api/types.ts +229 -0
  49. package/{scripts/rename-gitignore.js → src/api/utils.ts} +7 -6
  50. package/src/contract/contract.ts +663 -581
  51. package/src/contract/events.ts +8 -7
  52. package/src/contract/ralph.ts +29 -4
  53. package/src/global.ts +56 -0
  54. package/src/index.ts +7 -0
  55. package/src/signer/index.ts +0 -1
  56. package/src/signer/signer.ts +165 -134
  57. package/src/transaction/index.ts +0 -1
  58. package/src/transaction/status.ts +6 -3
  59. package/src/utils/bs58.ts +11 -0
  60. package/src/utils/index.ts +0 -1
  61. package/src/utils/subscription.ts +1 -5
  62. package/src/utils/utils.ts +15 -23
  63. package/webpack.config.js +3 -0
  64. package/.eslintrc.json +0 -21
  65. package/LICENSE +0 -165
  66. package/contracts/add/add.ral +0 -16
  67. package/contracts/greeter/greeter.ral +0 -7
  68. package/contracts/greeter/greeter_interface.ral +0 -3
  69. package/contracts/greeter_main.ral +0 -9
  70. package/contracts/main.ral +0 -6
  71. package/contracts/sub/sub.ral +0 -9
  72. package/dev/user.conf +0 -29
  73. package/dist/scripts/create-project.d.ts +0 -2
  74. package/dist/scripts/create-project.js +0 -124
  75. package/dist/scripts/rename-gitignore.d.ts +0 -1
  76. package/dist/scripts/start-devnet.d.ts +0 -1
  77. package/dist/scripts/start-devnet.js +0 -131
  78. package/dist/scripts/stop-devnet.d.ts +0 -1
  79. package/dist/scripts/stop-devnet.js +0 -32
  80. package/dist/src/signer/node-wallet.d.ts +0 -13
  81. package/dist/src/signer/node-wallet.js +0 -60
  82. package/dist/src/test/index.d.ts +0 -7
  83. package/dist/src/test/index.js +0 -41
  84. package/dist/src/test/privatekey-wallet.d.ts +0 -12
  85. package/dist/src/test/privatekey-wallet.js +0 -68
  86. package/dist/src/transaction/sign-verify.d.ts +0 -2
  87. package/dist/src/transaction/sign-verify.js +0 -58
  88. package/dist/src/utils/password-crypto.d.ts +0 -2
  89. package/dist/src/utils/password-crypto.js +0 -69
  90. package/gitignore +0 -10
  91. package/scripts/create-project.ts +0 -136
  92. package/scripts/start-devnet.js +0 -141
  93. package/scripts/stop-devnet.js +0 -32
  94. package/src/contract/ralph.test.ts +0 -178
  95. package/src/fixtures/address.json +0 -36
  96. package/src/fixtures/balance.json +0 -9
  97. package/src/fixtures/self-clique.json +0 -19
  98. package/src/fixtures/transaction.json +0 -13
  99. package/src/fixtures/transactions.json +0 -179
  100. package/src/signer/fixtures/genesis.json +0 -26
  101. package/src/signer/fixtures/wallets.json +0 -26
  102. package/src/signer/node-wallet.ts +0 -74
  103. package/src/test/index.ts +0 -32
  104. package/src/test/privatekey-wallet.ts +0 -58
  105. package/src/transaction/sign-verify.test.ts +0 -50
  106. package/src/transaction/sign-verify.ts +0 -39
  107. package/src/utils/address.test.ts +0 -47
  108. package/src/utils/djb2.test.ts +0 -35
  109. package/src/utils/password-crypto.test.ts +0 -27
  110. package/src/utils/password-crypto.ts +0 -77
  111. package/src/utils/utils.test.ts +0 -161
  112. package/templates/base/README.md +0 -34
  113. package/templates/base/package.json +0 -35
  114. package/templates/base/src/greeter.ts +0 -41
  115. package/templates/base/tsconfig.json +0 -19
  116. package/templates/react/README.md +0 -34
  117. package/templates/react/config-overrides.js +0 -18
  118. package/templates/react/package.json +0 -66
  119. package/templates/react/src/App.tsx +0 -42
  120. package/templates/react/src/artifacts/greeter.ral.json +0 -26
  121. package/templates/react/src/artifacts/greeter_main.ral.json +0 -22
  122. package/templates/shared/.eslintrc.json +0 -12
  123. package/templates/shared/scripts/header.js +0 -0
  124. package/test/contract.test.ts +0 -178
  125. package/test/events.test.ts +0 -138
  126. package/test/transaction.test.ts +0 -72
@@ -16,14 +16,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 { ContractEvent } from '../api/api-alephium'
19
+ import { web3 } from '..'
20
+ import { node } from '../api'
20
21
  import { Subscription, SubscribeOptions } from '../utils'
21
22
 
22
- export class EventSubscription extends Subscription<ContractEvent> {
23
+ export class EventSubscription extends Subscription<node.ContractEvent> {
23
24
  readonly contractAddress: string
24
25
  private fromCount: number
25
26
 
26
- constructor(options: SubscribeOptions<ContractEvent>, contractAddress: string, fromCount?: number) {
27
+ constructor(options: SubscribeOptions<node.ContractEvent>, contractAddress: string, fromCount?: number) {
27
28
  super(options)
28
29
  this.contractAddress = contractAddress
29
30
  this.fromCount = typeof fromCount === 'undefined' ? 0 : fromCount
@@ -31,7 +32,7 @@ export class EventSubscription extends Subscription<ContractEvent> {
31
32
  this.startPolling()
32
33
  }
33
34
 
34
- override startPolling() {
35
+ override startPolling(): void {
35
36
  this.eventEmitter.on('tick', async () => {
36
37
  await this.polling()
37
38
  })
@@ -42,9 +43,9 @@ export class EventSubscription extends Subscription<ContractEvent> {
42
43
  return this.fromCount
43
44
  }
44
45
 
45
- override async polling() {
46
+ override async polling(): Promise<void> {
46
47
  try {
47
- const events = await this.provider.events.getEventsContractContractaddress(this.contractAddress, {
48
+ const events = await web3.getCurrentNodeProvider().events.getEventsContractContractaddress(this.contractAddress, {
48
49
  start: this.fromCount
49
50
  })
50
51
  if (this.cancelled) {
@@ -67,7 +68,7 @@ export class EventSubscription extends Subscription<ContractEvent> {
67
68
  }
68
69
 
69
70
  export function subscribeToEvents(
70
- options: SubscribeOptions<ContractEvent>,
71
+ options: SubscribeOptions<node.ContractEvent>,
71
72
  contractAddress: string,
72
73
  fromCount?: number
73
74
  ): EventSubscription {
@@ -17,9 +17,9 @@ 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
21
  import { bs58, isHexString } from '../utils'
21
- import { node } from '../api'
22
- import { Fields, Val } from './contract'
22
+ import { Fields, FieldsSig } from './contract'
23
23
 
24
24
  const bigIntZero = BigInt(0)
25
25
 
@@ -236,7 +236,7 @@ export function encodeScriptField(tpe: string, value: Val): Uint8Array {
236
236
 
237
237
  const scriptFieldRegex = /\{([0-9]*)\}/g
238
238
 
239
- export function buildScriptByteCode(bytecodeTemplate: string, fields: Fields, fieldsSig: node.FieldsSig): string {
239
+ export function buildScriptByteCode(bytecodeTemplate: string, fields: Fields, fieldsSig: FieldsSig): string {
240
240
  return bytecodeTemplate.replace(scriptFieldRegex, (_, fieldIndex: string) => {
241
241
  const fieldName = fieldsSig.names[`${fieldIndex}`]
242
242
  const fieldType = fieldsSig.types[`${fieldIndex}`]
@@ -249,7 +249,7 @@ export function buildScriptByteCode(bytecodeTemplate: string, fields: Fields, fi
249
249
  })
250
250
  }
251
251
 
252
- export function buildContractByteCode(bytecode: string, fields: Fields, fieldsSig: node.FieldsSig): string {
252
+ export function buildContractByteCode(bytecode: string, fields: Fields, fieldsSig: FieldsSig): string {
253
253
  const fieldsEncoded = fieldsSig.names.flatMap((fieldName, fieldIndex) => {
254
254
  const fieldType = fieldsSig.types[`${fieldIndex}`]
255
255
  if (fieldName in fields) {
@@ -343,6 +343,31 @@ function invalidVal(tpe: string, value: Val): Error {
343
343
  return Error(`Invalid API value ${value} for type ${tpe}`)
344
344
  }
345
345
 
346
+ export function buildDebugBytecode(bytecode: string, bytecodePatch: string): string {
347
+ if (bytecodePatch === '') {
348
+ return bytecode
349
+ }
350
+
351
+ const pattern = /[=+-][0-9a-f]*/g
352
+ let result = ''
353
+ let index = 0
354
+ for (const parts of bytecodePatch.matchAll(pattern)) {
355
+ const part = parts[0]
356
+ const diffType = part[0]
357
+ if (diffType === '=') {
358
+ const length = parseInt(part.substring(1))
359
+ result = result + bytecode.slice(index, index + length)
360
+ index = index + length
361
+ } else if (diffType === '+') {
362
+ result = result + part.substring(1)
363
+ } else {
364
+ const length = parseInt(part.substring(1))
365
+ index = index + length
366
+ }
367
+ }
368
+ return result
369
+ }
370
+
346
371
  // export function buildContractByteCode(
347
372
  // compiled: node.TemplateContractByteCode,
348
373
  // templateVariables: TemplateVariables
package/src/global.ts ADDED
@@ -0,0 +1,56 @@
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 { ExplorerProvider, NodeProvider } from './api'
20
+
21
+ let _currentNodeProvider: NodeProvider | undefined = undefined
22
+
23
+ export function setCurrentNodeProvider(provider: NodeProvider): void
24
+ export function setCurrentNodeProvider(baseUrl: string, apiKey?: string): void
25
+ export function setCurrentNodeProvider(provider: NodeProvider | string, apiKey?: string): void {
26
+ if (typeof provider == 'string') {
27
+ _currentNodeProvider = new NodeProvider(provider, apiKey)
28
+ } else {
29
+ _currentNodeProvider = provider
30
+ }
31
+ }
32
+
33
+ export function getCurrentNodeProvider(): NodeProvider {
34
+ if (typeof _currentNodeProvider === 'undefined') {
35
+ throw Error('No node provider is set.')
36
+ }
37
+ return _currentNodeProvider
38
+ }
39
+
40
+ let _currentExplorerProvider: ExplorerProvider | undefined = undefined
41
+
42
+ export function setCurrentExplorerProvider(provider: ExplorerProvider): void
43
+ export function setCurrentExplorerProvider(baseUrl: string, apiKey?: string): void
44
+ export function setCurrentExplorerProvider(provider: ExplorerProvider | string, apiKey?: string): void {
45
+ if (typeof provider == 'string') {
46
+ _currentExplorerProvider = new ExplorerProvider(provider, apiKey)
47
+ } else {
48
+ _currentExplorerProvider = provider
49
+ }
50
+ }
51
+
52
+ // Different from `NodeProvider`, this may return `undefined`
53
+ // as ExplorerProvider is not necessary for all applications
54
+ export function getCurrentExplorerProvider(): ExplorerProvider | undefined {
55
+ return _currentExplorerProvider
56
+ }
package/src/index.ts CHANGED
@@ -16,6 +16,10 @@ 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
+ BigInt.prototype['toJSON'] = function () {
20
+ return this.toString()
21
+ }
22
+
19
23
  export * from './api'
20
24
  export * from './contract'
21
25
  export * from './signer'
@@ -23,3 +27,6 @@ export * from './utils'
23
27
  export * from './transaction'
24
28
 
25
29
  export * from './constants'
30
+ export * as web3 from './global'
31
+
32
+ export * as utils from './utils'
@@ -17,4 +17,3 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
19
  export * from './signer'
20
- export * from './node-wallet'
@@ -17,22 +17,25 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
19
  import { ec as EC } from 'elliptic'
20
- import { NodeProvider } from '../api'
20
+ import {
21
+ ExplorerProvider,
22
+ fromApiNumber256,
23
+ fromApiTokens,
24
+ NodeProvider,
25
+ Number256,
26
+ toApiNumber256,
27
+ toApiNumber256Optional,
28
+ toApiTokens,
29
+ Token
30
+ } from '../api'
21
31
  import { node } from '../api'
22
32
  import * as utils from '../utils'
23
33
  import { Eq, assertType } from '../utils'
24
34
  import blake from 'blakejs'
25
- import { Token } from '../api/api-alephium'
26
35
 
27
- const ec = new EC('secp256k1')
36
+ export type OutputRef = node.OutputRef
28
37
 
29
- export interface SignResult {
30
- fromGroup: number
31
- toGroup: number
32
- unsignedTx: string
33
- txId: string
34
- signature: string
35
- }
38
+ const ec = new EC('secp256k1')
36
39
 
37
40
  export interface Account {
38
41
  address: string
@@ -40,42 +43,39 @@ export interface Account {
40
43
  publicKey: string
41
44
  }
42
45
 
43
- export type SubmitTx = { submitTx?: boolean }
44
46
  export type SignerAddress = { signerAddress: string }
45
- type TxBuildParams<T> = Omit<T, 'fromPublicKey'> & SignerAddress & SubmitTx
46
-
47
- export type GetAccountsParams = undefined
48
- export type GetAccountsResult = Account[]
47
+ type TxBuildParams<T> = Omit<T, 'fromPublicKey' | 'targetBlockHash'> & SignerAddress
48
+ type SignResult<T> = Omit<T, 'gasPrice'> & { signature: string; gasPrice: Number256 }
49
49
 
50
50
  export interface SignTransferTxParams {
51
51
  signerAddress: string
52
- destinations: node.Destination[]
53
- utxos?: node.OutputRef[]
52
+ destinations: Destination[]
53
+ utxos?: OutputRef[]
54
54
  gasAmount?: number
55
- gasPrice?: string
56
- submitTx?: boolean
55
+ gasPrice?: Number256
57
56
  }
58
- assertType<Eq<SignTransferTxParams, TxBuildParams<node.BuildTransaction>>>()
57
+ assertType<Eq<keyof SignTransferTxParams, keyof TxBuildParams<node.BuildTransaction>>>()
59
58
  export interface SignTransferTxResult {
60
59
  fromGroup: number
61
60
  toGroup: number
62
61
  unsignedTx: string
63
62
  txId: string
64
63
  signature: string
64
+ gasAmount: number
65
+ gasPrice: Number256
65
66
  }
66
- assertType<Eq<SignTransferTxResult, SignResult>>()
67
+ assertType<Eq<SignTransferTxResult, SignResult<node.BuildTransactionResult>>>()
67
68
 
68
69
  export interface SignDeployContractTxParams {
69
70
  signerAddress: string
70
71
  bytecode: string
71
- initialAttoAlphAmount?: string
72
+ initialAttoAlphAmount?: Number256
72
73
  initialTokenAmounts?: Token[]
73
- issueTokenAmount?: string
74
+ issueTokenAmount?: Number256
74
75
  gasAmount?: number
75
- gasPrice?: string
76
- submitTx?: boolean
76
+ gasPrice?: Number256
77
77
  }
78
- assertType<Eq<SignDeployContractTxParams, TxBuildParams<node.BuildDeployContractTx>>>()
78
+ assertType<Eq<keyof SignDeployContractTxParams, keyof TxBuildParams<node.BuildDeployContractTx>>>()
79
79
  export interface SignDeployContractTxResult {
80
80
  fromGroup: number
81
81
  toGroup: number
@@ -84,52 +84,46 @@ export interface SignDeployContractTxResult {
84
84
  signature: string
85
85
  contractId: string
86
86
  contractAddress: string
87
+ gasAmount: number
88
+ gasPrice: Number256
87
89
  }
88
- assertType<Eq<SignDeployContractTxResult, SignResult & { contractId: string; contractAddress: string }>>()
90
+ assertType<Eq<SignDeployContractTxResult, SignResult<node.BuildDeployContractTxResult> & { contractId: string }>>()
89
91
 
90
92
  export interface SignExecuteScriptTxParams {
91
93
  signerAddress: string
92
94
  bytecode: string
93
- attoAlphAmount?: string
94
- tokens?: node.Token[]
95
+ attoAlphAmount?: Number256
96
+ tokens?: Token[]
95
97
  gasAmount?: number
96
- gasPrice?: string
97
- submitTx?: boolean
98
+ gasPrice?: Number256
98
99
  }
99
- assertType<Eq<SignExecuteScriptTxParams, TxBuildParams<node.BuildExecuteScriptTx>>>()
100
+ assertType<Eq<keyof SignExecuteScriptTxParams, keyof TxBuildParams<node.BuildExecuteScriptTx>>>()
100
101
  export interface SignExecuteScriptTxResult {
101
102
  fromGroup: number
102
103
  toGroup: number
103
104
  unsignedTx: string
104
105
  txId: string
105
106
  signature: string
107
+ gasAmount: number
108
+ gasPrice: Number256
106
109
  }
107
- assertType<Eq<SignExecuteScriptTxResult, SignResult>>()
110
+ assertType<Eq<SignExecuteScriptTxResult, SignResult<node.BuildExecuteScriptTxResult>>>()
108
111
 
109
112
  export interface SignUnsignedTxParams {
110
113
  signerAddress: string
111
114
  unsignedTx: string
112
- submitTx?: boolean
113
115
  }
114
- assertType<Eq<SignUnsignedTxParams, { unsignedTx: string } & SubmitTx & SignerAddress>>()
116
+ assertType<Eq<SignUnsignedTxParams, { unsignedTx: string } & SignerAddress>>()
115
117
  export interface SignUnsignedTxResult {
116
118
  fromGroup: number
117
119
  toGroup: number
118
120
  unsignedTx: string
119
121
  txId: string
120
122
  signature: string
123
+ gasAmount: number
124
+ gasPrice: Number256
121
125
  }
122
- assertType<Eq<SignUnsignedTxResult, SignResult>>()
123
-
124
- export interface SignHexStringParams {
125
- signerAddress: string
126
- hexString: string
127
- }
128
- assertType<Eq<SignHexStringParams, { hexString: string } & SignerAddress>>()
129
- export interface SignHexStringResult {
130
- signature: string
131
- }
132
- assertType<Eq<SignHexStringResult, Pick<SignResult, 'signature'>>>()
126
+ assertType<Eq<SignUnsignedTxResult, SignTransferTxResult>>
133
127
 
134
128
  export interface SignMessageParams {
135
129
  signerAddress: string
@@ -139,144 +133,150 @@ assertType<Eq<SignMessageParams, { message: string } & SignerAddress>>()
139
133
  export interface SignMessageResult {
140
134
  signature: string
141
135
  }
142
- assertType<Eq<SignMessageResult, Pick<SignResult, 'signature'>>>()
136
+
137
+ export interface SubmitTransactionParams {
138
+ unsignedTx: string
139
+ signature: string
140
+ }
141
+ export interface SubmissionResult {
142
+ txId: string
143
+ fromGroup: number
144
+ toGroup: number
145
+ }
143
146
 
144
147
  export interface SignerProvider {
145
- getAccounts(): Promise<Account[]>
146
- signTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult>
147
- signDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult>
148
- signExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult>
148
+ get nodeProvider(): NodeProvider | undefined
149
+ get explorerProvider(): ExplorerProvider | undefined
150
+
151
+ getSelectedAccount(): Promise<Account>
152
+
153
+ signAndSubmitTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult>
154
+ signAndSubmitDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult>
155
+ signAndSubmitExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult>
156
+ signAndSubmitUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult>
157
+
149
158
  signUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult>
150
- signHexString(params: SignHexStringParams): Promise<SignHexStringResult>
159
+ // The message will be prefixed with 'Alephium Signed Message: ' before signing
160
+ // so that the resulted signature cannot be reused for building transactions.
151
161
  signMessage(params: SignMessageParams): Promise<SignMessageResult>
152
162
  }
153
163
 
154
- export abstract class SignerWithNodeProvider implements SignerProvider {
155
- readonly provider: NodeProvider
156
- alwaysSubmitTx: boolean
157
-
158
- abstract getAccounts(): Promise<Account[]>
164
+ export abstract class SignerProviderSimple implements SignerProvider {
165
+ abstract get nodeProvider(): NodeProvider | undefined
166
+ abstract get explorerProvider(): ExplorerProvider | undefined
167
+ abstract getSelectedAccount(): Promise<Account>
159
168
 
160
- async getAccount(signerAddress: string): Promise<Account> {
161
- const accounts = await this.getAccounts()
162
- const account = accounts.find((a) => a.address === signerAddress)
163
- if (typeof account === 'undefined') {
164
- throw new Error('Unmatched signerAddress')
165
- } else {
166
- return account
169
+ private getNodeProvider(): NodeProvider {
170
+ if (this.nodeProvider === undefined) {
171
+ throw Error('The signer does not contain a node provider')
167
172
  }
173
+ return this.nodeProvider
168
174
  }
169
175
 
170
- constructor(provider: NodeProvider, alwaysSubmitTx: boolean) {
171
- this.provider = provider
172
- this.alwaysSubmitTx = alwaysSubmitTx
176
+ async submitTransaction(params: SubmitTransactionParams): Promise<SubmissionResult> {
177
+ const data: node.SubmitTransaction = { unsignedTx: params.unsignedTx, signature: params.signature }
178
+ return this.getNodeProvider().transactions.postTransactionsSubmit(data)
173
179
  }
174
180
 
175
- private async defaultSignerAddress(): Promise<string> {
176
- return (await this.getAccounts())[0].address
181
+ async signAndSubmitTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult> {
182
+ const signResult = await this.signTransferTx(params)
183
+ await this.submitTransaction(signResult)
184
+ return signResult
177
185
  }
178
-
179
- async submitTransaction(unsignedTx: string, txHash: string, signerAddress?: string): Promise<SubmissionResult> {
180
- const address = typeof signerAddress !== 'undefined' ? signerAddress : await this.defaultSignerAddress()
181
- const signature = await this.signRaw(address, txHash)
182
- const params: node.SubmitTransaction = { unsignedTx: unsignedTx, signature: signature }
183
- return this.provider.transactions.postTransactionsSubmit(params)
186
+ async signAndSubmitDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult> {
187
+ const signResult = await this.signDeployContractTx(params)
188
+ await this.submitTransaction(signResult)
189
+ return signResult
184
190
  }
185
-
186
- private shouldSubmitTx(params: SubmitTx): boolean {
187
- return this.alwaysSubmitTx || (params.submitTx ? params.submitTx : true)
191
+ async signAndSubmitExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult> {
192
+ const signResult = await this.signExecuteScriptTx(params)
193
+ await this.submitTransaction(signResult)
194
+ return signResult
195
+ }
196
+ async signAndSubmitUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult> {
197
+ const signResult = await this.signUnsignedTx(params)
198
+ await this.submitTransaction(signResult)
199
+ return signResult
188
200
  }
189
201
 
190
202
  private async usePublicKey<T extends SignerAddress>(
191
203
  params: T
192
204
  ): Promise<Omit<T, 'signerAddress'> & { fromPublicKey: string }> {
193
205
  const { signerAddress, ...restParams } = params
194
- const allAccounts = await this.getAccounts()
195
- const signerAccount = allAccounts.find((account) => account.address === signerAddress)
196
- if (typeof signerAccount === 'undefined') {
197
- throw new Error('Unknown signer address')
206
+ const selectedAccount = await this.getSelectedAccount()
207
+ if (signerAddress !== selectedAccount.address) {
208
+ throw new Error('The signer address is not the selected address')
198
209
  } else {
199
- return { fromPublicKey: signerAccount.publicKey, ...restParams }
210
+ return { fromPublicKey: selectedAccount.publicKey, ...restParams }
200
211
  }
201
212
  }
202
213
 
203
214
  async signTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult> {
204
215
  const response = await this.buildTransferTx(params)
205
- return this.handleSign({ signerAddress: params.signerAddress, ...response }, this.shouldSubmitTx(params))
216
+ const signature = await this.signRaw(params.signerAddress, response.txId)
217
+ return { ...response, signature, gasPrice: fromApiNumber256(response.gasPrice) }
206
218
  }
207
219
 
208
220
  async buildTransferTx(params: SignTransferTxParams): Promise<node.BuildTransactionResult> {
209
- return this.provider.transactions.postTransactionsBuild(await this.usePublicKey(params))
221
+ const data: node.BuildTransaction = {
222
+ ...(await this.usePublicKey(params)),
223
+ destinations: toApiDestinations(params.destinations),
224
+ gasPrice: toApiNumber256Optional(params.gasPrice)
225
+ }
226
+ return this.getNodeProvider().transactions.postTransactionsBuild(data)
210
227
  }
211
228
 
212
229
  async signDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult> {
213
230
  const response = await this.buildContractCreationTx(params)
214
- const result = await this.handleSign(
215
- { signerAddress: params.signerAddress, ...response },
216
- this.shouldSubmitTx(params)
217
- )
231
+ const signature = await this.signRaw(params.signerAddress, response.txId)
218
232
  const contractId = utils.binToHex(utils.contractIdFromAddress(response.contractAddress))
219
- return { ...result, contractId: contractId, contractAddress: response.contractAddress }
233
+ return { ...response, contractId, signature, gasPrice: fromApiNumber256(response.gasPrice) }
220
234
  }
221
235
 
222
236
  async buildContractCreationTx(params: SignDeployContractTxParams): Promise<node.BuildDeployContractTxResult> {
223
- return this.provider.contracts.postContractsUnsignedTxDeployContract(await this.usePublicKey(params))
237
+ const data: node.BuildDeployContractTx = {
238
+ ...(await this.usePublicKey(params)),
239
+ initialAttoAlphAmount: toApiNumber256Optional(params.initialAttoAlphAmount),
240
+ initialTokenAmounts: toApiTokens(params.initialTokenAmounts),
241
+ issueTokenAmount: toApiNumber256Optional(params.issueTokenAmount),
242
+ gasPrice: toApiNumber256Optional(params.gasPrice)
243
+ }
244
+ return this.getNodeProvider().contracts.postContractsUnsignedTxDeployContract(data)
224
245
  }
225
246
 
226
247
  async signExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult> {
227
248
  const response = await this.buildScriptTx(params)
228
- return this.handleSign({ signerAddress: params.signerAddress, ...response }, this.shouldSubmitTx(params))
249
+ const signature = await this.signRaw(params.signerAddress, response.txId)
250
+ return { ...response, signature, gasPrice: fromApiNumber256(response.gasPrice) }
229
251
  }
230
252
 
231
253
  async buildScriptTx(params: SignExecuteScriptTxParams): Promise<node.BuildExecuteScriptTxResult> {
232
- return this.provider.contracts.postContractsUnsignedTxExecuteScript(await this.usePublicKey(params))
254
+ const data: node.BuildExecuteScriptTx = {
255
+ ...(await this.usePublicKey(params)),
256
+ attoAlphAmount: toApiNumber256Optional(params.attoAlphAmount),
257
+ tokens: toApiTokens(params.tokens),
258
+ gasPrice: toApiNumber256Optional(params.gasPrice)
259
+ }
260
+ return this.getNodeProvider().contracts.postContractsUnsignedTxExecuteScript(data)
233
261
  }
234
262
 
235
263
  // in general, wallet should show the decoded information to user for confirmation
236
264
  // please overwrite this function for real wallet
237
265
  async signUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult> {
238
266
  const data = { unsignedTx: params.unsignedTx }
239
- const decoded = await this.provider.transactions.postTransactionsDecodeUnsignedTx(data)
240
- return this.handleSign(
241
- {
242
- fromGroup: decoded.fromGroup,
243
- toGroup: decoded.toGroup,
244
- signerAddress: params.signerAddress,
245
- unsignedTx: params.unsignedTx,
246
- txId: decoded.unsignedTx.txId
247
- },
248
- params.submitTx ? params.submitTx : true // we don't consider `alwaysSubmitTx` as the tx might needs multiple signatures
249
- )
250
- }
251
-
252
- protected async handleSign(
253
- response: { fromGroup: number; toGroup: number; signerAddress: string; unsignedTx: string; txId: string },
254
- submitTx: boolean
255
- ): Promise<SignResult> {
256
- // sign the tx
257
- const signature = await this.signRaw(response.signerAddress, response.txId)
258
- // submit the tx if required
259
- if (submitTx) {
260
- await this.provider.transactions.postTransactionsSubmit({
261
- unsignedTx: response.unsignedTx,
262
- signature: signature
263
- })
264
- }
265
- // return the signature back to the provider
267
+ const decoded = await this.getNodeProvider().transactions.postTransactionsDecodeUnsignedTx(data)
268
+ const signature = await this.signRaw(params.signerAddress, decoded.unsignedTx.txId)
266
269
  return {
267
- fromGroup: response.fromGroup,
268
- toGroup: response.toGroup,
269
- unsignedTx: response.unsignedTx,
270
- txId: response.txId,
271
- signature: signature
270
+ fromGroup: decoded.fromGroup,
271
+ toGroup: decoded.toGroup,
272
+ unsignedTx: params.unsignedTx,
273
+ txId: decoded.unsignedTx.txId,
274
+ signature,
275
+ gasAmount: decoded.unsignedTx.gasAmount,
276
+ gasPrice: fromApiNumber256(decoded.unsignedTx.gasPrice)
272
277
  }
273
278
  }
274
279
 
275
- async signHexString(params: SignHexStringParams): Promise<SignHexStringResult> {
276
- const signature = await this.signRaw(params.signerAddress, params.hexString)
277
- return { signature: signature }
278
- }
279
-
280
280
  async signMessage(params: SignMessageParams): Promise<SignMessageResult> {
281
281
  const extendedMessage = extendMessage(params.message)
282
282
  const messageHash = blake.blake2b(extendedMessage, undefined, 32)
@@ -287,10 +287,20 @@ export abstract class SignerWithNodeProvider implements SignerProvider {
287
287
  abstract signRaw(signerAddress: string, hexString: string): Promise<string>
288
288
  }
289
289
 
290
- export interface SubmissionResult {
291
- txId: string
292
- fromGroup: number
293
- toGroup: number
290
+ export abstract class SignerProviderWithMultipleAccounts extends SignerProviderSimple {
291
+ abstract getAccounts(): Promise<Account[]>
292
+
293
+ async getAccount(signerAddress: string): Promise<Account> {
294
+ const accounts = await this.getAccounts()
295
+ const account = accounts.find((a) => a.address === signerAddress)
296
+ if (typeof account === 'undefined') {
297
+ throw new Error('Unmatched signerAddress')
298
+ } else {
299
+ return account
300
+ }
301
+ }
302
+
303
+ abstract setSelectedAccount(address: string): Promise<void>
294
304
  }
295
305
 
296
306
  export function verifyHexString(hexString: string, publicKey: string, signature: string): boolean {
@@ -311,3 +321,24 @@ export function verifySignedMessage(message: string, publicKey: string, signatur
311
321
  const messageHash = blake.blake2b(extendedMessage, undefined, 32)
312
322
  return verifyHexString(utils.binToHex(messageHash), publicKey, signature)
313
323
  }
324
+
325
+ export interface Destination {
326
+ address: string
327
+ attoAlphAmount: Number256
328
+ tokens?: Token[]
329
+ lockTime?: number
330
+ message?: string
331
+ }
332
+ assertType<Eq<keyof Destination, keyof node.Destination>>
333
+
334
+ export function toApiDestination(data: Destination): node.Destination {
335
+ return { ...data, attoAlphAmount: toApiNumber256(data.attoAlphAmount), tokens: toApiTokens(data.tokens) }
336
+ }
337
+
338
+ export function toApiDestinations(data: Destination[]): node.Destination[] {
339
+ return data.map(toApiDestination)
340
+ }
341
+
342
+ export function fromApiDestination(data: node.Destination): Destination {
343
+ return { ...data, attoAlphAmount: fromApiNumber256(data.attoAlphAmount), tokens: fromApiTokens(data.tokens) }
344
+ }
@@ -16,5 +16,4 @@ 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
- export * from './sign-verify'
20
19
  export * from './status'
@@ -16,9 +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 { TxStatus } from '../api/api-alephium'
19
+ import { web3 } from '..'
20
+ import { node } from '../api'
20
21
  import { Subscription, SubscribeOptions } from '../utils'
21
22
 
23
+ export type TxStatus = node.TxStatus
24
+
22
25
  export class TxStatusSubscription extends Subscription<TxStatus> {
23
26
  readonly txId: string
24
27
  readonly fromGroup?: number
@@ -33,9 +36,9 @@ export class TxStatusSubscription extends Subscription<TxStatus> {
33
36
  this.startPolling()
34
37
  }
35
38
 
36
- override async polling() {
39
+ override async polling(): Promise<void> {
37
40
  try {
38
- const txStatus = await this.provider.transactions.getTransactionsStatus({
41
+ const txStatus = await web3.getCurrentNodeProvider().transactions.getTransactionsStatus({
39
42
  txId: this.txId,
40
43
  fromGroup: this.fromGroup,
41
44
  toGroup: this.toGroup