@alephium/web3 0.3.0-rc.4 → 0.3.0-rc.7
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.
- package/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/src/api/api-alephium.d.ts +1 -1
- package/dist/src/api/api-alephium.js +1 -1
- package/dist/src/api/api-explorer.d.ts +91 -21
- package/dist/src/api/api-explorer.js +64 -31
- package/dist/src/api/index.d.ts +0 -1
- package/dist/src/api/index.js +0 -2
- package/dist/src/contract/contract.d.ts +21 -21
- package/dist/src/contract/contract.js +103 -108
- package/dist/src/signer/index.d.ts +2 -0
- package/dist/src/signer/index.js +2 -0
- package/dist/src/signer/signer.d.ts +30 -107
- package/dist/src/signer/signer.js +63 -68
- package/dist/src/signer/tx-builder.d.ts +17 -0
- package/dist/src/signer/tx-builder.js +93 -0
- package/dist/src/signer/types.d.ts +121 -0
- package/dist/src/signer/types.js +30 -0
- package/package.json +4 -3
- package/src/api/api-alephium.ts +1 -1
- package/src/api/api-explorer.ts +134 -36
- package/src/api/index.ts +0 -2
- package/src/contract/contract.ts +143 -121
- package/src/signer/index.ts +2 -0
- package/src/signer/signer.ts +112 -188
- package/src/signer/tx-builder.ts +121 -0
- package/src/signer/types.ts +155 -0
- package/webpack.config.js +1 -0
package/src/signer/signer.ts
CHANGED
|
@@ -17,138 +17,43 @@ 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 {
|
|
21
|
-
ExplorerProvider,
|
|
22
|
-
fromApiNumber256,
|
|
23
|
-
fromApiTokens,
|
|
24
|
-
NodeProvider,
|
|
25
|
-
Number256,
|
|
26
|
-
toApiNumber256,
|
|
27
|
-
toApiNumber256Optional,
|
|
28
|
-
toApiTokens,
|
|
29
|
-
Token
|
|
30
|
-
} from '../api'
|
|
20
|
+
import { ExplorerProvider, fromApiNumber256, fromApiTokens, NodeProvider, toApiNumber256, toApiTokens } from '../api'
|
|
31
21
|
import { node } from '../api'
|
|
32
22
|
import * as utils from '../utils'
|
|
33
|
-
import { Eq, assertType } from '../utils'
|
|
34
23
|
import blake from 'blakejs'
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
import {
|
|
25
|
+
Account,
|
|
26
|
+
Address,
|
|
27
|
+
EnableOptionsBase,
|
|
28
|
+
Destination,
|
|
29
|
+
SignDeployContractTxParams,
|
|
30
|
+
SignDeployContractTxResult,
|
|
31
|
+
SignerAddress,
|
|
32
|
+
SignExecuteScriptTxParams,
|
|
33
|
+
SignExecuteScriptTxResult,
|
|
34
|
+
SignMessageParams,
|
|
35
|
+
SignMessageResult,
|
|
36
|
+
SignTransferTxParams,
|
|
37
|
+
SignTransferTxResult,
|
|
38
|
+
SignUnsignedTxParams,
|
|
39
|
+
SignUnsignedTxResult,
|
|
40
|
+
SubmissionResult,
|
|
41
|
+
SubmitTransactionParams,
|
|
42
|
+
ExtSignTransferTxParams,
|
|
43
|
+
ExtSignDeployContractTxParams,
|
|
44
|
+
ExtSignExecuteScriptTxParams,
|
|
45
|
+
ExtSignUnsignedTxParams,
|
|
46
|
+
ExtSignMessageParams
|
|
47
|
+
} from './types'
|
|
48
|
+
import { TransactionBuilder } from './tx-builder'
|
|
37
49
|
|
|
38
50
|
const ec = new EC('secp256k1')
|
|
39
51
|
|
|
40
|
-
export interface Account {
|
|
41
|
-
address: string
|
|
42
|
-
group: number
|
|
43
|
-
publicKey: string
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export type SignerAddress = { signerAddress: string }
|
|
47
|
-
type TxBuildParams<T> = Omit<T, 'fromPublicKey' | 'targetBlockHash'> & SignerAddress
|
|
48
|
-
type SignResult<T> = Omit<T, 'gasPrice'> & { signature: string; gasPrice: Number256 }
|
|
49
|
-
|
|
50
|
-
export interface SignTransferTxParams {
|
|
51
|
-
signerAddress: string
|
|
52
|
-
destinations: Destination[]
|
|
53
|
-
utxos?: OutputRef[]
|
|
54
|
-
gasAmount?: number
|
|
55
|
-
gasPrice?: Number256
|
|
56
|
-
}
|
|
57
|
-
assertType<Eq<keyof SignTransferTxParams, keyof TxBuildParams<node.BuildTransaction>>>()
|
|
58
|
-
export interface SignTransferTxResult {
|
|
59
|
-
fromGroup: number
|
|
60
|
-
toGroup: number
|
|
61
|
-
unsignedTx: string
|
|
62
|
-
txId: string
|
|
63
|
-
signature: string
|
|
64
|
-
gasAmount: number
|
|
65
|
-
gasPrice: Number256
|
|
66
|
-
}
|
|
67
|
-
assertType<Eq<SignTransferTxResult, SignResult<node.BuildTransactionResult>>>()
|
|
68
|
-
|
|
69
|
-
export interface SignDeployContractTxParams {
|
|
70
|
-
signerAddress: string
|
|
71
|
-
bytecode: string
|
|
72
|
-
initialAttoAlphAmount?: Number256
|
|
73
|
-
initialTokenAmounts?: Token[]
|
|
74
|
-
issueTokenAmount?: Number256
|
|
75
|
-
gasAmount?: number
|
|
76
|
-
gasPrice?: Number256
|
|
77
|
-
}
|
|
78
|
-
assertType<Eq<keyof SignDeployContractTxParams, keyof TxBuildParams<node.BuildDeployContractTx>>>()
|
|
79
|
-
export interface SignDeployContractTxResult {
|
|
80
|
-
fromGroup: number
|
|
81
|
-
toGroup: number
|
|
82
|
-
unsignedTx: string
|
|
83
|
-
txId: string
|
|
84
|
-
signature: string
|
|
85
|
-
contractId: string
|
|
86
|
-
contractAddress: string
|
|
87
|
-
gasAmount: number
|
|
88
|
-
gasPrice: Number256
|
|
89
|
-
}
|
|
90
|
-
assertType<Eq<SignDeployContractTxResult, SignResult<node.BuildDeployContractTxResult> & { contractId: string }>>()
|
|
91
|
-
|
|
92
|
-
export interface SignExecuteScriptTxParams {
|
|
93
|
-
signerAddress: string
|
|
94
|
-
bytecode: string
|
|
95
|
-
attoAlphAmount?: Number256
|
|
96
|
-
tokens?: Token[]
|
|
97
|
-
gasAmount?: number
|
|
98
|
-
gasPrice?: Number256
|
|
99
|
-
}
|
|
100
|
-
assertType<Eq<keyof SignExecuteScriptTxParams, keyof TxBuildParams<node.BuildExecuteScriptTx>>>()
|
|
101
|
-
export interface SignExecuteScriptTxResult {
|
|
102
|
-
fromGroup: number
|
|
103
|
-
toGroup: number
|
|
104
|
-
unsignedTx: string
|
|
105
|
-
txId: string
|
|
106
|
-
signature: string
|
|
107
|
-
gasAmount: number
|
|
108
|
-
gasPrice: Number256
|
|
109
|
-
}
|
|
110
|
-
assertType<Eq<SignExecuteScriptTxResult, SignResult<node.BuildExecuteScriptTxResult>>>()
|
|
111
|
-
|
|
112
|
-
export interface SignUnsignedTxParams {
|
|
113
|
-
signerAddress: string
|
|
114
|
-
unsignedTx: string
|
|
115
|
-
}
|
|
116
|
-
assertType<Eq<SignUnsignedTxParams, { unsignedTx: string } & SignerAddress>>()
|
|
117
|
-
export interface SignUnsignedTxResult {
|
|
118
|
-
fromGroup: number
|
|
119
|
-
toGroup: number
|
|
120
|
-
unsignedTx: string
|
|
121
|
-
txId: string
|
|
122
|
-
signature: string
|
|
123
|
-
gasAmount: number
|
|
124
|
-
gasPrice: Number256
|
|
125
|
-
}
|
|
126
|
-
assertType<Eq<SignUnsignedTxResult, SignTransferTxResult>>
|
|
127
|
-
|
|
128
|
-
export interface SignMessageParams {
|
|
129
|
-
signerAddress: string
|
|
130
|
-
message: string
|
|
131
|
-
}
|
|
132
|
-
assertType<Eq<SignMessageParams, { message: string } & SignerAddress>>()
|
|
133
|
-
export interface SignMessageResult {
|
|
134
|
-
signature: string
|
|
135
|
-
}
|
|
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
|
-
}
|
|
146
|
-
|
|
147
52
|
export interface SignerProvider {
|
|
148
53
|
get nodeProvider(): NodeProvider | undefined
|
|
149
54
|
get explorerProvider(): ExplorerProvider | undefined
|
|
150
55
|
|
|
151
|
-
|
|
56
|
+
getSelectedAddress(): Promise<Address>
|
|
152
57
|
|
|
153
58
|
signAndSubmitTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult>
|
|
154
59
|
signAndSubmitDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult>
|
|
@@ -161,21 +66,34 @@ export interface SignerProvider {
|
|
|
161
66
|
signMessage(params: SignMessageParams): Promise<SignMessageResult>
|
|
162
67
|
}
|
|
163
68
|
|
|
164
|
-
|
|
165
|
-
|
|
69
|
+
// Abstraction for interactive signer (e.g. WalletConnect instance, Extension wallet object)
|
|
70
|
+
export interface InteractiveSignerProvider<EnableOptions extends EnableOptionsBase = EnableOptionsBase>
|
|
71
|
+
extends SignerProvider {
|
|
72
|
+
enable(opt?: EnableOptions): Promise<Address>
|
|
73
|
+
disconnect(): Promise<void>
|
|
74
|
+
|
|
75
|
+
// Methods inherited from SignerProvider, but require networkId in the params
|
|
76
|
+
signAndSubmitTransferTx(params: ExtSignTransferTxParams): Promise<SignTransferTxResult>
|
|
77
|
+
signAndSubmitDeployContractTx(params: ExtSignDeployContractTxParams): Promise<SignDeployContractTxResult>
|
|
78
|
+
signAndSubmitExecuteScriptTx(params: ExtSignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult>
|
|
79
|
+
signAndSubmitUnsignedTx(params: ExtSignUnsignedTxParams): Promise<SignUnsignedTxResult>
|
|
80
|
+
signUnsignedTx(params: ExtSignUnsignedTxParams): Promise<SignUnsignedTxResult>
|
|
81
|
+
signMessage(params: ExtSignMessageParams): Promise<SignMessageResult>
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export abstract class SignerProviderSimple extends TransactionBuilder implements SignerProvider {
|
|
166
85
|
abstract get explorerProvider(): ExplorerProvider | undefined
|
|
86
|
+
|
|
167
87
|
abstract getSelectedAccount(): Promise<Account>
|
|
168
88
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
return this.nodeProvider
|
|
89
|
+
async getSelectedAddress(): Promise<Address> {
|
|
90
|
+
const account = await this.getSelectedAccount()
|
|
91
|
+
return account.address
|
|
174
92
|
}
|
|
175
93
|
|
|
176
94
|
async submitTransaction(params: SubmitTransactionParams): Promise<SubmissionResult> {
|
|
177
95
|
const data: node.SubmitTransaction = { unsignedTx: params.unsignedTx, signature: params.signature }
|
|
178
|
-
return this.
|
|
96
|
+
return this.nodeProvider.transactions.postTransactionsSubmit(data)
|
|
179
97
|
}
|
|
180
98
|
|
|
181
99
|
async signAndSubmitTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult> {
|
|
@@ -199,82 +117,56 @@ export abstract class SignerProviderSimple implements SignerProvider {
|
|
|
199
117
|
return signResult
|
|
200
118
|
}
|
|
201
119
|
|
|
120
|
+
protected abstract getPublicKey(address: string): Promise<string>
|
|
121
|
+
|
|
202
122
|
private async usePublicKey<T extends SignerAddress>(
|
|
203
123
|
params: T
|
|
204
124
|
): Promise<Omit<T, 'signerAddress'> & { fromPublicKey: string }> {
|
|
205
125
|
const { signerAddress, ...restParams } = params
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
throw new Error('The signer address is not the selected address')
|
|
209
|
-
} else {
|
|
210
|
-
return { fromPublicKey: selectedAccount.publicKey, ...restParams }
|
|
211
|
-
}
|
|
126
|
+
const publicKey = await this.getPublicKey(signerAddress)
|
|
127
|
+
return { fromPublicKey: publicKey, ...restParams }
|
|
212
128
|
}
|
|
213
129
|
|
|
214
130
|
async signTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult> {
|
|
215
131
|
const response = await this.buildTransferTx(params)
|
|
216
132
|
const signature = await this.signRaw(params.signerAddress, response.txId)
|
|
217
|
-
return {
|
|
133
|
+
return { signature, ...response }
|
|
218
134
|
}
|
|
219
135
|
|
|
220
|
-
async buildTransferTx(params: SignTransferTxParams): Promise<
|
|
221
|
-
|
|
222
|
-
...(await this.usePublicKey(params)),
|
|
223
|
-
destinations: toApiDestinations(params.destinations),
|
|
224
|
-
gasPrice: toApiNumber256Optional(params.gasPrice)
|
|
225
|
-
}
|
|
226
|
-
return this.getNodeProvider().transactions.postTransactionsBuild(data)
|
|
136
|
+
override async buildTransferTx(params: SignTransferTxParams): Promise<Omit<SignTransferTxResult, 'signature'>> {
|
|
137
|
+
return super.buildTransferTx(params, await this.getPublicKey(params.signerAddress))
|
|
227
138
|
}
|
|
228
139
|
|
|
229
140
|
async signDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult> {
|
|
230
|
-
const response = await this.
|
|
141
|
+
const response = await this.buildDeployContractTx(params)
|
|
231
142
|
const signature = await this.signRaw(params.signerAddress, response.txId)
|
|
232
|
-
|
|
233
|
-
return { ...response, contractId, signature, gasPrice: fromApiNumber256(response.gasPrice) }
|
|
143
|
+
return { signature, ...response }
|
|
234
144
|
}
|
|
235
145
|
|
|
236
|
-
async
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
initialTokenAmounts: toApiTokens(params.initialTokenAmounts),
|
|
241
|
-
issueTokenAmount: toApiNumber256Optional(params.issueTokenAmount),
|
|
242
|
-
gasPrice: toApiNumber256Optional(params.gasPrice)
|
|
243
|
-
}
|
|
244
|
-
return this.getNodeProvider().contracts.postContractsUnsignedTxDeployContract(data)
|
|
146
|
+
override async buildDeployContractTx(
|
|
147
|
+
params: SignDeployContractTxParams
|
|
148
|
+
): Promise<Omit<SignDeployContractTxResult, 'signature'>> {
|
|
149
|
+
return super.buildDeployContractTx(params, await this.getPublicKey(params.signerAddress))
|
|
245
150
|
}
|
|
246
151
|
|
|
247
152
|
async signExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult> {
|
|
248
|
-
const response = await this.
|
|
153
|
+
const response = await this.buildExecuteScriptTx(params)
|
|
249
154
|
const signature = await this.signRaw(params.signerAddress, response.txId)
|
|
250
|
-
return {
|
|
155
|
+
return { signature, ...response }
|
|
251
156
|
}
|
|
252
157
|
|
|
253
|
-
async
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
tokens: toApiTokens(params.tokens),
|
|
258
|
-
gasPrice: toApiNumber256Optional(params.gasPrice)
|
|
259
|
-
}
|
|
260
|
-
return this.getNodeProvider().contracts.postContractsUnsignedTxExecuteScript(data)
|
|
158
|
+
override async buildExecuteScriptTx(
|
|
159
|
+
params: SignExecuteScriptTxParams
|
|
160
|
+
): Promise<Omit<SignExecuteScriptTxResult, 'signature'>> {
|
|
161
|
+
return super.buildExecuteScriptTx(params, await this.getPublicKey(params.signerAddress))
|
|
261
162
|
}
|
|
262
163
|
|
|
263
164
|
// in general, wallet should show the decoded information to user for confirmation
|
|
264
165
|
// please overwrite this function for real wallet
|
|
265
166
|
async signUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult> {
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
return {
|
|
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)
|
|
277
|
-
}
|
|
167
|
+
const response = await this.buildUnsignedTx(params)
|
|
168
|
+
const signature = await this.signRaw(params.signerAddress, response.txId)
|
|
169
|
+
return { signature, ...response }
|
|
278
170
|
}
|
|
279
171
|
|
|
280
172
|
async signMessage(params: SignMessageParams): Promise<SignMessageResult> {
|
|
@@ -288,6 +180,8 @@ export abstract class SignerProviderSimple implements SignerProvider {
|
|
|
288
180
|
}
|
|
289
181
|
|
|
290
182
|
export abstract class SignerProviderWithMultipleAccounts extends SignerProviderSimple {
|
|
183
|
+
abstract setSelectedAddress(address: string): Promise<void>
|
|
184
|
+
|
|
291
185
|
abstract getAccounts(): Promise<Account[]>
|
|
292
186
|
|
|
293
187
|
async getAccount(signerAddress: string): Promise<Account> {
|
|
@@ -300,7 +194,46 @@ export abstract class SignerProviderWithMultipleAccounts extends SignerProviderS
|
|
|
300
194
|
}
|
|
301
195
|
}
|
|
302
196
|
|
|
303
|
-
|
|
197
|
+
async getPublicKey(signerAddress: string): Promise<string> {
|
|
198
|
+
const account = await this.getAccount(signerAddress)
|
|
199
|
+
return account.publicKey
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export abstract class SignerProviderWithCachedAccounts<T extends Account> extends SignerProviderWithMultipleAccounts {
|
|
204
|
+
private _selectedAccount: T | undefined = undefined
|
|
205
|
+
protected readonly _accounts = new Map<Address, T>()
|
|
206
|
+
|
|
207
|
+
getSelectedAccount(): Promise<T> {
|
|
208
|
+
if (this._selectedAccount === undefined) {
|
|
209
|
+
throw Error('No account is selected yet')
|
|
210
|
+
} else {
|
|
211
|
+
return Promise.resolve(this._selectedAccount)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
setSelectedAddress(address: string): Promise<void> {
|
|
216
|
+
const accountOpt = this._accounts.get(address)
|
|
217
|
+
if (accountOpt === undefined) {
|
|
218
|
+
throw Error('The address is not in the accounts')
|
|
219
|
+
} else {
|
|
220
|
+
this._selectedAccount = accountOpt
|
|
221
|
+
return Promise.resolve()
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
getAccounts(): Promise<T[]> {
|
|
226
|
+
return Promise.resolve(Array.from(this._accounts.values()))
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
override async getAccount(address: string): Promise<T> {
|
|
230
|
+
const account = this._accounts.get(address)
|
|
231
|
+
if (account === undefined) {
|
|
232
|
+
throw Error('The address is not in the accounts')
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return Promise.resolve(account)
|
|
236
|
+
}
|
|
304
237
|
}
|
|
305
238
|
|
|
306
239
|
export function verifyHexString(hexString: string, publicKey: string, signature: string): boolean {
|
|
@@ -322,15 +255,6 @@ export function verifySignedMessage(message: string, publicKey: string, signatur
|
|
|
322
255
|
return verifyHexString(utils.binToHex(messageHash), publicKey, signature)
|
|
323
256
|
}
|
|
324
257
|
|
|
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
258
|
export function toApiDestination(data: Destination): node.Destination {
|
|
335
259
|
return { ...data, attoAlphAmount: toApiNumber256(data.attoAlphAmount), tokens: toApiTokens(data.tokens) }
|
|
336
260
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
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 { utils } from '..'
|
|
20
|
+
import { fromApiNumber256, node, NodeProvider, toApiNumber256Optional, toApiTokens } from '../api'
|
|
21
|
+
import { addressFromPublicKey } from '../utils'
|
|
22
|
+
import { toApiDestinations } from './signer'
|
|
23
|
+
import {
|
|
24
|
+
SignDeployContractTxParams,
|
|
25
|
+
SignDeployContractTxResult,
|
|
26
|
+
SignerAddress,
|
|
27
|
+
SignExecuteScriptTxParams,
|
|
28
|
+
SignExecuteScriptTxResult,
|
|
29
|
+
SignTransferTxParams,
|
|
30
|
+
SignTransferTxResult,
|
|
31
|
+
SignUnsignedTxParams,
|
|
32
|
+
SignUnsignedTxResult
|
|
33
|
+
} from './types'
|
|
34
|
+
|
|
35
|
+
export abstract class TransactionBuilder {
|
|
36
|
+
abstract get nodeProvider(): NodeProvider
|
|
37
|
+
|
|
38
|
+
static create(baseUrl: string, apiKey?: string) {
|
|
39
|
+
const nodeProvider = new NodeProvider(baseUrl, apiKey)
|
|
40
|
+
return new (class extends TransactionBuilder {
|
|
41
|
+
get nodeProvider(): NodeProvider {
|
|
42
|
+
return nodeProvider
|
|
43
|
+
}
|
|
44
|
+
})()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private static validatePublicKey(params: SignerAddress, publicKey: string) {
|
|
48
|
+
const address = addressFromPublicKey(publicKey)
|
|
49
|
+
if (address !== params.signerAddress) {
|
|
50
|
+
throw new Error('Unmatched public key')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async buildTransferTx(
|
|
55
|
+
params: SignTransferTxParams,
|
|
56
|
+
publicKey: string
|
|
57
|
+
): Promise<Omit<SignTransferTxResult, 'signature'>> {
|
|
58
|
+
TransactionBuilder.validatePublicKey(params, publicKey)
|
|
59
|
+
|
|
60
|
+
const { destinations, gasPrice, ...rest } = params
|
|
61
|
+
const data: node.BuildTransaction = {
|
|
62
|
+
fromPublicKey: publicKey,
|
|
63
|
+
destinations: toApiDestinations(destinations),
|
|
64
|
+
gasPrice: toApiNumber256Optional(gasPrice),
|
|
65
|
+
...rest
|
|
66
|
+
}
|
|
67
|
+
const response = await this.nodeProvider.transactions.postTransactionsBuild(data)
|
|
68
|
+
return { ...response, gasPrice: fromApiNumber256(response.gasPrice) }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async buildDeployContractTx(
|
|
72
|
+
params: SignDeployContractTxParams,
|
|
73
|
+
publicKey: string
|
|
74
|
+
): Promise<Omit<SignDeployContractTxResult, 'signature'>> {
|
|
75
|
+
TransactionBuilder.validatePublicKey(params, publicKey)
|
|
76
|
+
|
|
77
|
+
const { initialAttoAlphAmount, initialTokenAmounts, issueTokenAmount, gasPrice, ...rest } = params
|
|
78
|
+
const data: node.BuildDeployContractTx = {
|
|
79
|
+
fromPublicKey: publicKey,
|
|
80
|
+
initialAttoAlphAmount: toApiNumber256Optional(initialAttoAlphAmount),
|
|
81
|
+
initialTokenAmounts: toApiTokens(initialTokenAmounts),
|
|
82
|
+
issueTokenAmount: toApiNumber256Optional(issueTokenAmount),
|
|
83
|
+
gasPrice: toApiNumber256Optional(gasPrice),
|
|
84
|
+
...rest
|
|
85
|
+
}
|
|
86
|
+
const response = await this.nodeProvider.contracts.postContractsUnsignedTxDeployContract(data)
|
|
87
|
+
const contractId = utils.binToHex(utils.contractIdFromAddress(response.contractAddress))
|
|
88
|
+
return { ...response, contractId, gasPrice: fromApiNumber256(response.gasPrice) }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async buildExecuteScriptTx(
|
|
92
|
+
params: SignExecuteScriptTxParams,
|
|
93
|
+
publicKey: string
|
|
94
|
+
): Promise<Omit<SignExecuteScriptTxResult, 'signature'>> {
|
|
95
|
+
TransactionBuilder.validatePublicKey(params, publicKey)
|
|
96
|
+
|
|
97
|
+
const { attoAlphAmount, tokens, gasPrice, ...rest } = params
|
|
98
|
+
const data: node.BuildExecuteScriptTx = {
|
|
99
|
+
fromPublicKey: publicKey,
|
|
100
|
+
attoAlphAmount: toApiNumber256Optional(attoAlphAmount),
|
|
101
|
+
tokens: toApiTokens(tokens),
|
|
102
|
+
gasPrice: toApiNumber256Optional(gasPrice),
|
|
103
|
+
...rest
|
|
104
|
+
}
|
|
105
|
+
const response = await this.nodeProvider.contracts.postContractsUnsignedTxExecuteScript(data)
|
|
106
|
+
return { ...response, gasPrice: fromApiNumber256(response.gasPrice) }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async buildUnsignedTx(params: SignUnsignedTxParams): Promise<Omit<SignUnsignedTxResult, 'signature'>> {
|
|
110
|
+
const data = { unsignedTx: params.unsignedTx }
|
|
111
|
+
const decoded = await this.nodeProvider.transactions.postTransactionsDecodeUnsignedTx(data)
|
|
112
|
+
return {
|
|
113
|
+
fromGroup: decoded.fromGroup,
|
|
114
|
+
toGroup: decoded.toGroup,
|
|
115
|
+
unsignedTx: params.unsignedTx,
|
|
116
|
+
txId: decoded.unsignedTx.txId,
|
|
117
|
+
gasAmount: decoded.unsignedTx.gasAmount,
|
|
118
|
+
gasPrice: fromApiNumber256(decoded.unsignedTx.gasPrice)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
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 { Number256, Token } from '../api'
|
|
20
|
+
import { node } from '../api'
|
|
21
|
+
import { Eq, assertType } from '../utils'
|
|
22
|
+
|
|
23
|
+
export type Address = string
|
|
24
|
+
|
|
25
|
+
export type OutputRef = node.OutputRef
|
|
26
|
+
|
|
27
|
+
export interface Destination {
|
|
28
|
+
address: string
|
|
29
|
+
attoAlphAmount: Number256
|
|
30
|
+
tokens?: Token[]
|
|
31
|
+
lockTime?: number
|
|
32
|
+
message?: string
|
|
33
|
+
}
|
|
34
|
+
assertType<Eq<keyof Destination, keyof node.Destination>>
|
|
35
|
+
|
|
36
|
+
export interface Account {
|
|
37
|
+
address: string
|
|
38
|
+
group: number
|
|
39
|
+
publicKey: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type SignerAddress = { signerAddress: string }
|
|
43
|
+
type TxBuildParams<T> = Omit<T, 'fromPublicKey' | 'targetBlockHash'> & SignerAddress
|
|
44
|
+
type SignResult<T> = Omit<T, 'gasPrice'> & { signature: string; gasPrice: Number256 }
|
|
45
|
+
|
|
46
|
+
export interface SignTransferTxParams {
|
|
47
|
+
signerAddress: string
|
|
48
|
+
destinations: Destination[]
|
|
49
|
+
utxos?: OutputRef[]
|
|
50
|
+
gasAmount?: number
|
|
51
|
+
gasPrice?: Number256
|
|
52
|
+
}
|
|
53
|
+
assertType<Eq<keyof SignTransferTxParams, keyof TxBuildParams<node.BuildTransaction>>>()
|
|
54
|
+
export interface SignTransferTxResult {
|
|
55
|
+
fromGroup: number
|
|
56
|
+
toGroup: number
|
|
57
|
+
unsignedTx: string
|
|
58
|
+
txId: string
|
|
59
|
+
signature: string
|
|
60
|
+
gasAmount: number
|
|
61
|
+
gasPrice: Number256
|
|
62
|
+
}
|
|
63
|
+
assertType<Eq<SignTransferTxResult, SignResult<node.BuildTransactionResult>>>()
|
|
64
|
+
|
|
65
|
+
export interface SignDeployContractTxParams {
|
|
66
|
+
signerAddress: string
|
|
67
|
+
bytecode: string
|
|
68
|
+
initialAttoAlphAmount?: Number256
|
|
69
|
+
initialTokenAmounts?: Token[]
|
|
70
|
+
issueTokenAmount?: Number256
|
|
71
|
+
gasAmount?: number
|
|
72
|
+
gasPrice?: Number256
|
|
73
|
+
}
|
|
74
|
+
assertType<Eq<keyof SignDeployContractTxParams, keyof TxBuildParams<node.BuildDeployContractTx>>>()
|
|
75
|
+
export interface SignDeployContractTxResult {
|
|
76
|
+
fromGroup: number
|
|
77
|
+
toGroup: number
|
|
78
|
+
unsignedTx: string
|
|
79
|
+
txId: string
|
|
80
|
+
signature: string
|
|
81
|
+
contractId: string
|
|
82
|
+
contractAddress: string
|
|
83
|
+
gasAmount: number
|
|
84
|
+
gasPrice: Number256
|
|
85
|
+
}
|
|
86
|
+
assertType<Eq<SignDeployContractTxResult, SignResult<node.BuildDeployContractTxResult> & { contractId: string }>>()
|
|
87
|
+
|
|
88
|
+
export interface SignExecuteScriptTxParams {
|
|
89
|
+
signerAddress: string
|
|
90
|
+
bytecode: string
|
|
91
|
+
attoAlphAmount?: Number256
|
|
92
|
+
tokens?: Token[]
|
|
93
|
+
gasAmount?: number
|
|
94
|
+
gasPrice?: Number256
|
|
95
|
+
}
|
|
96
|
+
assertType<Eq<keyof SignExecuteScriptTxParams, keyof TxBuildParams<node.BuildExecuteScriptTx>>>()
|
|
97
|
+
export interface SignExecuteScriptTxResult {
|
|
98
|
+
fromGroup: number
|
|
99
|
+
toGroup: number
|
|
100
|
+
unsignedTx: string
|
|
101
|
+
txId: string
|
|
102
|
+
signature: string
|
|
103
|
+
gasAmount: number
|
|
104
|
+
gasPrice: Number256
|
|
105
|
+
}
|
|
106
|
+
assertType<Eq<SignExecuteScriptTxResult, SignResult<node.BuildExecuteScriptTxResult>>>()
|
|
107
|
+
|
|
108
|
+
export interface SignUnsignedTxParams {
|
|
109
|
+
signerAddress: string
|
|
110
|
+
unsignedTx: string
|
|
111
|
+
}
|
|
112
|
+
assertType<Eq<SignUnsignedTxParams, { unsignedTx: string } & SignerAddress>>()
|
|
113
|
+
export interface SignUnsignedTxResult {
|
|
114
|
+
fromGroup: number
|
|
115
|
+
toGroup: number
|
|
116
|
+
unsignedTx: string
|
|
117
|
+
txId: string
|
|
118
|
+
signature: string
|
|
119
|
+
gasAmount: number
|
|
120
|
+
gasPrice: Number256
|
|
121
|
+
}
|
|
122
|
+
assertType<Eq<SignUnsignedTxResult, SignTransferTxResult>>
|
|
123
|
+
|
|
124
|
+
export interface SignMessageParams {
|
|
125
|
+
signerAddress: string
|
|
126
|
+
message: string
|
|
127
|
+
}
|
|
128
|
+
assertType<Eq<SignMessageParams, { message: string } & SignerAddress>>()
|
|
129
|
+
export interface SignMessageResult {
|
|
130
|
+
signature: string
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface SubmitTransactionParams {
|
|
134
|
+
unsignedTx: string
|
|
135
|
+
signature: string
|
|
136
|
+
}
|
|
137
|
+
export interface SubmissionResult {
|
|
138
|
+
txId: string
|
|
139
|
+
fromGroup: number
|
|
140
|
+
toGroup: number
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface EnableOptionsBase {
|
|
144
|
+
// chainGroup - specify whether to use addresses from a specific group
|
|
145
|
+
chainGroup?: number
|
|
146
|
+
networkId: string
|
|
147
|
+
onDisconnected: () => Promise<void>
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Transaction Params for InteractiveSignerProvider
|
|
151
|
+
export type ExtSignTransferTxParams = SignTransferTxParams & { networkId: string }
|
|
152
|
+
export type ExtSignDeployContractTxParams = SignDeployContractTxParams & { networkId: string }
|
|
153
|
+
export type ExtSignExecuteScriptTxParams = SignExecuteScriptTxParams & { networkId: string }
|
|
154
|
+
export type ExtSignUnsignedTxParams = SignUnsignedTxParams & { networkId: string }
|
|
155
|
+
export type ExtSignMessageParams = SignMessageParams & { networkId: string }
|