@alephium/web3 0.0.1-test.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.
- package/.editorconfig +13 -0
- package/.eslintignore +2 -0
- package/.eslintrc.json +21 -0
- package/.gitattributes +1 -0
- package/LICENSE +165 -0
- package/README.md +136 -0
- package/contracts/add.ral +16 -0
- package/contracts/greeter.ral +7 -0
- package/contracts/greeter_interface.ral +3 -0
- package/contracts/greeter_main.ral +9 -0
- package/contracts/main.ral +6 -0
- package/contracts/sub.ral +9 -0
- package/dev/user.conf +29 -0
- package/dist/alephium-web3.min.js +3 -0
- package/dist/alephium-web3.min.js.LICENSE.txt +27 -0
- package/dist/alephium-web3.min.js.map +1 -0
- package/dist/scripts/check-versions.d.ts +1 -0
- package/dist/scripts/check-versions.js +39 -0
- package/dist/scripts/create-project.d.ts +2 -0
- package/dist/scripts/create-project.js +124 -0
- package/dist/scripts/header.d.ts +0 -0
- package/dist/scripts/header.js +18 -0
- package/dist/scripts/rename-gitignore.d.ts +1 -0
- package/dist/scripts/rename-gitignore.js +24 -0
- package/dist/scripts/start-devnet.d.ts +1 -0
- package/dist/scripts/start-devnet.js +131 -0
- package/dist/scripts/stop-devnet.d.ts +1 -0
- package/dist/scripts/stop-devnet.js +32 -0
- package/dist/src/api/api-alephium.d.ts +1473 -0
- package/dist/src/api/api-alephium.js +1143 -0
- package/dist/src/api/api-explorer.d.ts +475 -0
- package/dist/src/api/api-explorer.js +457 -0
- package/dist/src/api/index.d.ts +10 -0
- package/dist/src/api/index.js +55 -0
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/constants.js +22 -0
- package/dist/src/contract/contract.d.ts +182 -0
- package/dist/src/contract/contract.js +760 -0
- package/dist/src/contract/events.d.ts +11 -0
- package/dist/src/contract/events.js +64 -0
- package/dist/src/contract/index.d.ts +3 -0
- package/dist/src/contract/index.js +32 -0
- package/dist/src/contract/ralph.d.ts +12 -0
- package/dist/src/contract/ralph.js +362 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +35 -0
- package/dist/src/signer/index.d.ts +2 -0
- package/dist/src/signer/index.js +31 -0
- package/dist/src/signer/node-wallet.d.ts +13 -0
- package/dist/src/signer/node-wallet.js +60 -0
- package/dist/src/signer/signer.d.ts +143 -0
- package/dist/src/signer/signer.js +184 -0
- package/dist/src/test/index.d.ts +7 -0
- package/dist/src/test/index.js +41 -0
- package/dist/src/test/privatekey-wallet.d.ts +12 -0
- package/dist/src/test/privatekey-wallet.js +68 -0
- package/dist/src/transaction/index.d.ts +2 -0
- package/dist/src/transaction/index.js +31 -0
- package/dist/src/transaction/sign-verify.d.ts +2 -0
- package/dist/src/transaction/sign-verify.js +58 -0
- package/dist/src/transaction/status.d.ts +10 -0
- package/dist/src/transaction/status.js +48 -0
- package/dist/src/utils/address.d.ts +1 -0
- package/dist/src/utils/address.js +42 -0
- package/dist/src/utils/bs58.d.ts +4 -0
- package/dist/src/utils/bs58.js +28 -0
- package/dist/src/utils/djb2.d.ts +1 -0
- package/dist/src/utils/djb2.js +27 -0
- package/dist/src/utils/index.d.ts +6 -0
- package/dist/src/utils/index.js +35 -0
- package/dist/src/utils/password-crypto.d.ts +2 -0
- package/dist/src/utils/password-crypto.js +69 -0
- package/dist/src/utils/subscription.d.ts +24 -0
- package/dist/src/utils/subscription.js +52 -0
- package/dist/src/utils/utils.d.ts +30 -0
- package/dist/src/utils/utils.js +199 -0
- package/gitignore +10 -0
- package/package.json +127 -0
- package/scripts/check-versions.js +45 -0
- package/scripts/create-project.ts +136 -0
- package/scripts/header.js +17 -0
- package/scripts/rename-gitignore.js +24 -0
- package/scripts/start-devnet.js +141 -0
- package/scripts/stop-devnet.js +32 -0
- package/src/api/api-alephium.ts +2430 -0
- package/src/api/api-explorer.ts +852 -0
- package/src/api/index.ts +35 -0
- package/src/constants.ts +20 -0
- package/src/contract/contract.ts +1014 -0
- package/src/contract/events.ts +75 -0
- package/src/contract/index.ts +21 -0
- package/src/contract/ralph.test.ts +178 -0
- package/src/contract/ralph.ts +362 -0
- package/src/fixtures/address.json +36 -0
- package/src/fixtures/balance.json +9 -0
- package/src/fixtures/self-clique.json +19 -0
- package/src/fixtures/transaction.json +13 -0
- package/src/fixtures/transactions.json +179 -0
- package/src/index.ts +25 -0
- package/src/signer/fixtures/genesis.json +26 -0
- package/src/signer/fixtures/wallets.json +26 -0
- package/src/signer/index.ts +20 -0
- package/src/signer/node-wallet.ts +74 -0
- package/src/signer/signer.ts +313 -0
- package/src/test/index.ts +32 -0
- package/src/test/privatekey-wallet.ts +58 -0
- package/src/transaction/index.ts +20 -0
- package/src/transaction/sign-verify.test.ts +50 -0
- package/src/transaction/sign-verify.ts +39 -0
- package/src/transaction/status.ts +58 -0
- package/src/utils/address.test.ts +47 -0
- package/src/utils/address.ts +39 -0
- package/src/utils/bs58.ts +26 -0
- package/src/utils/djb2.test.ts +35 -0
- package/src/utils/djb2.ts +25 -0
- package/src/utils/index.ts +24 -0
- package/src/utils/password-crypto.test.ts +27 -0
- package/src/utils/password-crypto.ts +77 -0
- package/src/utils/subscription.ts +72 -0
- package/src/utils/utils.test.ts +160 -0
- package/src/utils/utils.ts +209 -0
- package/templates/base/README.md +34 -0
- package/templates/base/package.json +35 -0
- package/templates/base/src/greeter.ts +41 -0
- package/templates/base/tsconfig.json +19 -0
- package/templates/react/README.md +34 -0
- package/templates/react/config-overrides.js +18 -0
- package/templates/react/package.json +66 -0
- package/templates/react/src/App.tsx +42 -0
- package/templates/react/src/artifacts/greeter.ral.json +26 -0
- package/templates/react/src/artifacts/greeter_main.ral.json +22 -0
- package/templates/shared/.eslintrc.json +12 -0
- package/templates/shared/scripts/header.js +0 -0
- package/test/contract.test.ts +161 -0
- package/test/events.test.ts +138 -0
- package/test/transaction.test.ts +72 -0
- package/webpack.config.js +57 -0
|
@@ -0,0 +1,313 @@
|
|
|
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 { ec as EC } from 'elliptic'
|
|
20
|
+
import { NodeProvider } from '../api'
|
|
21
|
+
import { node } from '../api'
|
|
22
|
+
import * as utils from '../utils'
|
|
23
|
+
import { Eq, assertType } from '../utils'
|
|
24
|
+
import blake from 'blakejs'
|
|
25
|
+
import { Token } from '../api/api-alephium'
|
|
26
|
+
|
|
27
|
+
const ec = new EC('secp256k1')
|
|
28
|
+
|
|
29
|
+
export interface SignResult {
|
|
30
|
+
fromGroup: number
|
|
31
|
+
toGroup: number
|
|
32
|
+
unsignedTx: string
|
|
33
|
+
txId: string
|
|
34
|
+
signature: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface Account {
|
|
38
|
+
address: string
|
|
39
|
+
group: number
|
|
40
|
+
publicKey: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type SubmitTx = { submitTx?: boolean }
|
|
44
|
+
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[]
|
|
49
|
+
|
|
50
|
+
export interface SignTransferTxParams {
|
|
51
|
+
signerAddress: string
|
|
52
|
+
destinations: node.Destination[]
|
|
53
|
+
utxos?: node.OutputRef[]
|
|
54
|
+
gasAmount?: number
|
|
55
|
+
gasPrice?: string
|
|
56
|
+
submitTx?: boolean
|
|
57
|
+
}
|
|
58
|
+
assertType<Eq<SignTransferTxParams, TxBuildParams<node.BuildTransaction>>>()
|
|
59
|
+
export interface SignTransferTxResult {
|
|
60
|
+
fromGroup: number
|
|
61
|
+
toGroup: number
|
|
62
|
+
unsignedTx: string
|
|
63
|
+
txId: string
|
|
64
|
+
signature: string
|
|
65
|
+
}
|
|
66
|
+
assertType<Eq<SignTransferTxResult, SignResult>>()
|
|
67
|
+
|
|
68
|
+
export interface SignDeployContractTxParams {
|
|
69
|
+
signerAddress: string
|
|
70
|
+
bytecode: string
|
|
71
|
+
initialAttoAlphAmount?: string
|
|
72
|
+
initialTokenAmounts?: Token[]
|
|
73
|
+
issueTokenAmount?: string
|
|
74
|
+
gasAmount?: number
|
|
75
|
+
gasPrice?: string
|
|
76
|
+
submitTx?: boolean
|
|
77
|
+
}
|
|
78
|
+
assertType<Eq<SignDeployContractTxParams, 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
|
+
}
|
|
88
|
+
assertType<Eq<SignDeployContractTxResult, SignResult & { contractId: string; contractAddress: string }>>()
|
|
89
|
+
|
|
90
|
+
export interface SignExecuteScriptTxParams {
|
|
91
|
+
signerAddress: string
|
|
92
|
+
bytecode: string
|
|
93
|
+
attoAlphAmount?: string
|
|
94
|
+
tokens?: node.Token[]
|
|
95
|
+
gasAmount?: number
|
|
96
|
+
gasPrice?: string
|
|
97
|
+
submitTx?: boolean
|
|
98
|
+
}
|
|
99
|
+
assertType<Eq<SignExecuteScriptTxParams, TxBuildParams<node.BuildExecuteScriptTx>>>()
|
|
100
|
+
export interface SignExecuteScriptTxResult {
|
|
101
|
+
fromGroup: number
|
|
102
|
+
toGroup: number
|
|
103
|
+
unsignedTx: string
|
|
104
|
+
txId: string
|
|
105
|
+
signature: string
|
|
106
|
+
}
|
|
107
|
+
assertType<Eq<SignExecuteScriptTxResult, SignResult>>()
|
|
108
|
+
|
|
109
|
+
export interface SignUnsignedTxParams {
|
|
110
|
+
signerAddress: string
|
|
111
|
+
unsignedTx: string
|
|
112
|
+
submitTx?: boolean
|
|
113
|
+
}
|
|
114
|
+
assertType<Eq<SignUnsignedTxParams, { unsignedTx: string } & SubmitTx & SignerAddress>>()
|
|
115
|
+
export interface SignUnsignedTxResult {
|
|
116
|
+
fromGroup: number
|
|
117
|
+
toGroup: number
|
|
118
|
+
unsignedTx: string
|
|
119
|
+
txId: string
|
|
120
|
+
signature: string
|
|
121
|
+
}
|
|
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'>>>()
|
|
133
|
+
|
|
134
|
+
export interface SignMessageParams {
|
|
135
|
+
signerAddress: string
|
|
136
|
+
message: string
|
|
137
|
+
}
|
|
138
|
+
assertType<Eq<SignMessageParams, { message: string } & SignerAddress>>()
|
|
139
|
+
export interface SignMessageResult {
|
|
140
|
+
signature: string
|
|
141
|
+
}
|
|
142
|
+
assertType<Eq<SignMessageResult, Pick<SignResult, 'signature'>>>()
|
|
143
|
+
|
|
144
|
+
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>
|
|
149
|
+
signUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult>
|
|
150
|
+
signHexString(params: SignHexStringParams): Promise<SignHexStringResult>
|
|
151
|
+
signMessage(params: SignMessageParams): Promise<SignMessageResult>
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export abstract class SignerWithNodeProvider implements SignerProvider {
|
|
155
|
+
readonly provider: NodeProvider
|
|
156
|
+
alwaysSubmitTx: boolean
|
|
157
|
+
|
|
158
|
+
abstract getAccounts(): Promise<Account[]>
|
|
159
|
+
|
|
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
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
constructor(provider: NodeProvider, alwaysSubmitTx: boolean) {
|
|
171
|
+
this.provider = provider
|
|
172
|
+
this.alwaysSubmitTx = alwaysSubmitTx
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private async defaultSignerAddress(): Promise<string> {
|
|
176
|
+
return (await this.getAccounts())[0].address
|
|
177
|
+
}
|
|
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)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private shouldSubmitTx(params: SubmitTx): boolean {
|
|
187
|
+
return this.alwaysSubmitTx || (params.submitTx ? params.submitTx : true)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private async usePublicKey<T extends SignerAddress>(
|
|
191
|
+
params: T
|
|
192
|
+
): Promise<Omit<T, 'signerAddress'> & { fromPublicKey: string }> {
|
|
193
|
+
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')
|
|
198
|
+
} else {
|
|
199
|
+
return { fromPublicKey: signerAccount.publicKey, ...restParams }
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async signTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult> {
|
|
204
|
+
const response = await this.buildTransferTx(params)
|
|
205
|
+
return this.handleSign({ signerAddress: params.signerAddress, ...response }, this.shouldSubmitTx(params))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async buildTransferTx(params: SignTransferTxParams): Promise<node.BuildTransactionResult> {
|
|
209
|
+
return this.provider.transactions.postTransactionsBuild(await this.usePublicKey(params))
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async signDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult> {
|
|
213
|
+
const response = await this.buildContractCreationTx(params)
|
|
214
|
+
const result = await this.handleSign(
|
|
215
|
+
{ signerAddress: params.signerAddress, ...response },
|
|
216
|
+
this.shouldSubmitTx(params)
|
|
217
|
+
)
|
|
218
|
+
const contractId = utils.binToHex(utils.contractIdFromAddress(response.contractAddress))
|
|
219
|
+
return { ...result, contractId: contractId, contractAddress: response.contractAddress }
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async buildContractCreationTx(params: SignDeployContractTxParams): Promise<node.BuildDeployContractTxResult> {
|
|
223
|
+
return this.provider.contracts.postContractsUnsignedTxDeployContract(await this.usePublicKey(params))
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async signExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult> {
|
|
227
|
+
const response = await this.buildScriptTx(params)
|
|
228
|
+
return this.handleSign({ signerAddress: params.signerAddress, ...response }, this.shouldSubmitTx(params))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async buildScriptTx(params: SignExecuteScriptTxParams): Promise<node.BuildExecuteScriptTxResult> {
|
|
232
|
+
return this.provider.contracts.postContractsUnsignedTxExecuteScript(await this.usePublicKey(params))
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// in general, wallet should show the decoded information to user for confirmation
|
|
236
|
+
// please overwrite this function for real wallet
|
|
237
|
+
async signUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult> {
|
|
238
|
+
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
|
|
266
|
+
return {
|
|
267
|
+
fromGroup: response.fromGroup,
|
|
268
|
+
toGroup: response.toGroup,
|
|
269
|
+
unsignedTx: response.unsignedTx,
|
|
270
|
+
txId: response.txId,
|
|
271
|
+
signature: signature
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async signHexString(params: SignHexStringParams): Promise<SignHexStringResult> {
|
|
276
|
+
const signature = await this.signRaw(params.signerAddress, params.hexString)
|
|
277
|
+
return { signature: signature }
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async signMessage(params: SignMessageParams): Promise<SignMessageResult> {
|
|
281
|
+
const extendedMessage = extendMessage(params.message)
|
|
282
|
+
const messageHash = blake.blake2b(extendedMessage, undefined, 32)
|
|
283
|
+
const signature = await this.signRaw(params.signerAddress, utils.binToHex(messageHash))
|
|
284
|
+
return { signature: signature }
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
abstract signRaw(signerAddress: string, hexString: string): Promise<string>
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export interface SubmissionResult {
|
|
291
|
+
txId: string
|
|
292
|
+
fromGroup: number
|
|
293
|
+
toGroup: number
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export function verifyHexString(hexString: string, publicKey: string, signature: string): boolean {
|
|
297
|
+
try {
|
|
298
|
+
const key = ec.keyFromPublic(publicKey, 'hex')
|
|
299
|
+
return key.verify(hexString, utils.signatureDecode(ec, signature))
|
|
300
|
+
} catch (error) {
|
|
301
|
+
return false
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function extendMessage(message: string): string {
|
|
306
|
+
return 'Alephium Signed Message: ' + message
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export function verifySignedMessage(message: string, publicKey: string, signature: string): boolean {
|
|
310
|
+
const extendedMessage = extendMessage(message)
|
|
311
|
+
const messageHash = blake.blake2b(extendedMessage, undefined, 32)
|
|
312
|
+
return verifyHexString(utils.binToHex(messageHash), publicKey, signature)
|
|
313
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
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 { NodeProvider } from '../api'
|
|
20
|
+
import { NodeWallet } from '../signer'
|
|
21
|
+
|
|
22
|
+
export const testWalletName = 'alephium-web3-test-only-wallet'
|
|
23
|
+
export const testAddress = '1DrDyTr9RpRsQnDnXo2YRiPzPW4ooHX5LLoqXrqfMrpQH'
|
|
24
|
+
export const testPassword = 'alph'
|
|
25
|
+
|
|
26
|
+
export async function testWallet(provider: NodeProvider): Promise<NodeWallet> {
|
|
27
|
+
const wallet = new NodeWallet(provider, testWalletName)
|
|
28
|
+
await wallet.unlock(testPassword)
|
|
29
|
+
return wallet
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export * from './privatekey-wallet'
|
|
@@ -0,0 +1,58 @@
|
|
|
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 { ec as EC } from 'elliptic'
|
|
20
|
+
import { NodeProvider } from '../api'
|
|
21
|
+
import { Account, SignerWithNodeProvider } from '../signer'
|
|
22
|
+
import * as utils from '../utils'
|
|
23
|
+
|
|
24
|
+
const ec = new EC('secp256k1')
|
|
25
|
+
|
|
26
|
+
export class PrivateKeyWallet extends SignerWithNodeProvider {
|
|
27
|
+
readonly privateKey: string
|
|
28
|
+
readonly publicKey: string
|
|
29
|
+
readonly address: string
|
|
30
|
+
readonly group: number
|
|
31
|
+
|
|
32
|
+
constructor(provider: NodeProvider, privateKey: string, alwaysSubmitTx = true) {
|
|
33
|
+
super(provider, alwaysSubmitTx)
|
|
34
|
+
this.privateKey = privateKey
|
|
35
|
+
this.publicKey = utils.publicKeyFromPrivateKey(privateKey)
|
|
36
|
+
this.address = utils.addressFromPublicKey(this.publicKey)
|
|
37
|
+
this.group = utils.groupOfAddress(this.address)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static Random(provider: NodeProvider, alwaysSubmitTx = true): PrivateKeyWallet {
|
|
41
|
+
const keyPair = ec.genKeyPair()
|
|
42
|
+
return new PrivateKeyWallet(provider, keyPair.getPrivate().toString('hex'), alwaysSubmitTx)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async getAccounts(): Promise<Account[]> {
|
|
46
|
+
return [{ address: this.address, publicKey: this.publicKey, group: this.group }]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async signRaw(signerAddress: string, hexString: string): Promise<string> {
|
|
50
|
+
if (signerAddress !== this.address) {
|
|
51
|
+
throw Error('Unmatched signer address')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const key = ec.keyFromPrivate(this.privateKey)
|
|
55
|
+
const signature = key.sign(hexString)
|
|
56
|
+
return utils.signatureEncode(signature)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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 * from './sign-verify'
|
|
20
|
+
export * from './status'
|
|
@@ -0,0 +1,50 @@
|
|
|
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 EC from 'elliptic'
|
|
20
|
+
import assert from 'assert'
|
|
21
|
+
|
|
22
|
+
import { transactionSign, transactionVerifySignature } from './sign-verify'
|
|
23
|
+
|
|
24
|
+
describe('transaction', function () {
|
|
25
|
+
it('should verify signature', () => {
|
|
26
|
+
const txHash = '8fc5f0d120b730f97f6cea5f02ae4a6ee7bf451d9261c623ea69d85e870201d2'
|
|
27
|
+
const pubKey = '02625b26ae1c5f7986475009e4037b3e6fe6320fde3c3f3332bea11ecadc35dd13'
|
|
28
|
+
const txSig =
|
|
29
|
+
'78471e7c97e558c98ac307ef699ed535ece319102fc69ea416dbb44fbb3cbf9c42dbfbf4ce73eb68c5e0d66122eb25d2ebe1cf9e37ef4c4f4e7a2ed35de141bc'
|
|
30
|
+
const unnormalizedSig =
|
|
31
|
+
'78471e7c97e558c98ac307ef699ed535ece319102fc69ea416dbb44fbb3cbf9cbd24040b318c14973a1f299edd14da2bcecd0d48775953ec71582fb97254ff85'
|
|
32
|
+
const wrongSig =
|
|
33
|
+
'88471e7c97e558c98ac307ef699ed535ece319102fc69ea416dbb44fbb3cbf9c42dbfbf4ce73eb68c5e0d66122eb25d2ebe1cf9e37ef4c4f4e7a2ed35de141bc'
|
|
34
|
+
|
|
35
|
+
assert.strictEqual(transactionVerifySignature(txHash, pubKey, txSig), true)
|
|
36
|
+
assert.strictEqual(transactionVerifySignature(txHash, pubKey, unnormalizedSig), false)
|
|
37
|
+
assert.strictEqual(transactionVerifySignature(txHash, pubKey, wrongSig), false)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('should sign and verify signature', () => {
|
|
41
|
+
const ec = new EC.ec('secp256k1')
|
|
42
|
+
const key = ec.genKeyPair()
|
|
43
|
+
const privateKey = key.getPrivate().toString('hex')
|
|
44
|
+
const publicKey = key.getPublic().encode('hex', true)
|
|
45
|
+
|
|
46
|
+
const txHash = '8fc5f0d120b730f97f6cea5f02ae4a6ee7bf451d9261c623ea69d85e870201d2'
|
|
47
|
+
const signature = transactionSign(txHash, privateKey)
|
|
48
|
+
assert.strictEqual(transactionVerifySignature(txHash, publicKey, signature), true)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
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 { ec as EC } from 'elliptic'
|
|
20
|
+
|
|
21
|
+
import * as utils from '../utils'
|
|
22
|
+
|
|
23
|
+
const ec = new EC('secp256k1')
|
|
24
|
+
|
|
25
|
+
export function transactionSign(txHash: string, privateKey: string): string {
|
|
26
|
+
const keyPair = ec.keyFromPrivate(privateKey)
|
|
27
|
+
const signature = keyPair.sign(txHash)
|
|
28
|
+
|
|
29
|
+
return utils.signatureEncode(signature)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function transactionVerifySignature(txHash: string, publicKey: string, signature: string): boolean {
|
|
33
|
+
try {
|
|
34
|
+
const key = ec.keyFromPublic(publicKey, 'hex')
|
|
35
|
+
return key.verify(txHash, utils.signatureDecode(ec, signature))
|
|
36
|
+
} catch (error) {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
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 { TxStatus } from '../api/api-alephium'
|
|
20
|
+
import { Subscription, SubscribeOptions } from '../utils'
|
|
21
|
+
|
|
22
|
+
export class TxStatusSubscription extends Subscription<TxStatus> {
|
|
23
|
+
readonly txId: string
|
|
24
|
+
readonly fromGroup?: number
|
|
25
|
+
readonly toGroup?: number
|
|
26
|
+
|
|
27
|
+
constructor(options: SubscribeOptions<TxStatus>, txId: string, fromGroup?: number, toGroup?: number) {
|
|
28
|
+
super(options)
|
|
29
|
+
this.txId = txId
|
|
30
|
+
this.fromGroup = fromGroup
|
|
31
|
+
this.toGroup = toGroup
|
|
32
|
+
|
|
33
|
+
this.startPolling()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override async polling() {
|
|
37
|
+
try {
|
|
38
|
+
const txStatus = await this.provider.transactions.getTransactionsStatus({
|
|
39
|
+
txId: this.txId,
|
|
40
|
+
fromGroup: this.fromGroup,
|
|
41
|
+
toGroup: this.toGroup
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
await this.messageCallback(txStatus)
|
|
45
|
+
} catch (err) {
|
|
46
|
+
await this.errorCallback(err, this)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function subscribeToTxStatus(
|
|
52
|
+
options: SubscribeOptions<TxStatus>,
|
|
53
|
+
txId: string,
|
|
54
|
+
fromGroup?: number,
|
|
55
|
+
toGroup?: number
|
|
56
|
+
): TxStatusSubscription {
|
|
57
|
+
return new TxStatusSubscription(options, txId, fromGroup, toGroup)
|
|
58
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
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 { addressToGroup } from './address'
|
|
20
|
+
|
|
21
|
+
describe('address', function () {
|
|
22
|
+
it('should derive group', async () => {
|
|
23
|
+
function check(address: string, expected: number) {
|
|
24
|
+
const group = addressToGroup(address, 4)
|
|
25
|
+
expect(group).toEqual(expected)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
check('12psscGPMgdqctaeCA37HYAkpVBFX1LbN4dSvjyxbDyKk', 1)
|
|
29
|
+
check('16TGLiD3fqyuGFRFHffh58BC3okYCbjRH1WHPzeSp39Wi', 2)
|
|
30
|
+
check('15aTcpJfCX9akQqYuRMMgun6Mv6ek8bigB98VTUFMwKYA', 1)
|
|
31
|
+
check('164ejvnxGYRPUt3tYwJrMxBLLmeag2WACH4GfcsRUN3W7', 2)
|
|
32
|
+
check('15p5vK921GnxFSQgXZo8Wceg6EvwcXZ9rCQxE2SeXc1s5', 1)
|
|
33
|
+
check('1HSLAetSuMTKPHukvXYg6yaDuUJ67vxGashzFLEuu6qV6', 1)
|
|
34
|
+
check('1HbU1TDiUMAj33Cp5cA2xc9uTqp1bjWa5UvkeGLm4bDbE', 2)
|
|
35
|
+
check('13zn4s3fb5Q9d8rtszYdmYVpQ3MM9VM2xLBe9rMhcNxjd', 0)
|
|
36
|
+
check('1DdQwce5ZzFrEYyz1H5KU9v8hRpoTbq5i7zE5Nu5k4ope', 2)
|
|
37
|
+
check('19hpcUVGzdpWRD8yVUyP9pJwwxD6P5ixGUgSmVPbhBAVX', 2)
|
|
38
|
+
check('1DpNeY8uutS1FRW7D565WjUgu5HcKSYAMqZNWgUJWggWZ', 0)
|
|
39
|
+
check('1G1gjpt4mxij7JwP5SpX6ScwQHisWN3V5WBtFfWKtc3vo', 3)
|
|
40
|
+
check('19XyGb6f1upjvQAG4vexB1EmY3pU8G2VN5gM267Pdhogg', 3)
|
|
41
|
+
check('1H5YniQrUqxJY9ShTjMeX6DMgjPpYfdFqDvTgBYv6h1iz', 1)
|
|
42
|
+
check('18Ca9jZDqRcxTfdNr2hq5KBJjf7PJLA5PXMjRoeB83JNv', 3)
|
|
43
|
+
check('15XyPNJuZ85wyUMs4mwn98LLPMjiwUSCuTmR74NuxpwXT', 0)
|
|
44
|
+
check('1F6ssQRwH1p1omaoQR3eirFrycHC3mUr3Vw9pLcgEe33W', 1)
|
|
45
|
+
check('19JtVnQ4YLcA9mWPafnLmtWarAjdaLR3d7R5RAUjxHbe1', 3)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
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 bs58 from './bs58'
|
|
20
|
+
import djb2 from './djb2'
|
|
21
|
+
|
|
22
|
+
export function addressToGroup(address: string, totalNumberOfGroups: number): number {
|
|
23
|
+
const bytes = bs58.decode(address).slice(1)
|
|
24
|
+
const value = djb2(bytes) | 1
|
|
25
|
+
const hash = toPosInt(xorByte(value))
|
|
26
|
+
const group = hash % totalNumberOfGroups
|
|
27
|
+
return group
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function xorByte(value: number): number {
|
|
31
|
+
const byte0 = value >> 24
|
|
32
|
+
const byte1 = value >> 16
|
|
33
|
+
const byte2 = value >> 8
|
|
34
|
+
return byte0 ^ byte1 ^ byte2 ^ value
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function toPosInt(byte: number): number {
|
|
38
|
+
return byte & 0xff
|
|
39
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
/** This source is under MIT License and come originally from https://github.com/cryptocoinjs/bs58 **/
|
|
20
|
+
import basex from 'base-x'
|
|
21
|
+
|
|
22
|
+
const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
|
23
|
+
|
|
24
|
+
export const bs58 = basex(ALPHABET)
|
|
25
|
+
|
|
26
|
+
export default bs58
|