@alephium/web3 0.2.0-rc.32 → 0.2.0-rc.33
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/index.d.ts +25 -12
- package/dist/src/api/index.js +11 -15
- package/dist/src/signer/signer.d.ts +10 -11
- package/dist/src/signer/signer.js +26 -6
- package/package.json +1 -1
- package/src/api/index.ts +36 -27
- package/src/signer/signer.ts +33 -17
package/dist/src/api/index.d.ts
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
import { Api as NodeApi } from './api-alephium';
|
|
2
2
|
import { Api as ExplorerApi } from './api-explorer';
|
|
3
|
-
|
|
4
|
-
wallets: NodeApi<string>['wallets'];
|
|
5
|
-
infos: NodeApi<string>['infos'];
|
|
6
|
-
blockflow: NodeApi<string>['blockflow'];
|
|
7
|
-
addresses: NodeApi<string>['addresses'];
|
|
8
|
-
transactions: NodeApi<string>['transactions'];
|
|
9
|
-
contracts: NodeApi<string>['contracts'];
|
|
10
|
-
multisig: NodeApi<string>['multisig'];
|
|
11
|
-
utils: NodeApi<string>['utils'];
|
|
12
|
-
miners: NodeApi<string>['miners'];
|
|
13
|
-
events: NodeApi<string>['events'];
|
|
3
|
+
interface INodeProvider {
|
|
4
|
+
readonly wallets: NodeApi<string>['wallets'];
|
|
5
|
+
readonly infos: NodeApi<string>['infos'];
|
|
6
|
+
readonly blockflow: NodeApi<string>['blockflow'];
|
|
7
|
+
readonly addresses: NodeApi<string>['addresses'];
|
|
8
|
+
readonly transactions: NodeApi<string>['transactions'];
|
|
9
|
+
readonly contracts: NodeApi<string>['contracts'];
|
|
10
|
+
readonly multisig: NodeApi<string>['multisig'];
|
|
11
|
+
readonly utils: NodeApi<string>['utils'];
|
|
12
|
+
readonly miners: NodeApi<string>['miners'];
|
|
13
|
+
readonly events: NodeApi<string>['events'];
|
|
14
|
+
}
|
|
15
|
+
export declare class NodeProvider implements INodeProvider {
|
|
16
|
+
readonly wallets: NodeApi<string>['wallets'];
|
|
17
|
+
readonly infos: NodeApi<string>['infos'];
|
|
18
|
+
readonly blockflow: NodeApi<string>['blockflow'];
|
|
19
|
+
readonly addresses: NodeApi<string>['addresses'];
|
|
20
|
+
readonly transactions: NodeApi<string>['transactions'];
|
|
21
|
+
readonly contracts: NodeApi<string>['contracts'];
|
|
22
|
+
readonly multisig: NodeApi<string>['multisig'];
|
|
23
|
+
readonly utils: NodeApi<string>['utils'];
|
|
24
|
+
readonly miners: NodeApi<string>['miners'];
|
|
25
|
+
readonly events: NodeApi<string>['events'];
|
|
26
|
+
constructor(provider: INodeProvider);
|
|
14
27
|
constructor(baseUrl: string, apiKey?: string);
|
|
15
|
-
|
|
28
|
+
static Proxy(nodeProvider: NodeProvider): NodeProvider;
|
|
16
29
|
}
|
|
17
30
|
export declare class ExplorerProvider extends ExplorerApi<null> {
|
|
18
31
|
constructor(baseUrl: string);
|
package/dist/src/api/index.js
CHANGED
|
@@ -56,8 +56,14 @@ function initializeNodeApi(baseUrl, apiKey) {
|
|
|
56
56
|
return nodeApi;
|
|
57
57
|
}
|
|
58
58
|
class NodeProvider {
|
|
59
|
-
constructor(
|
|
60
|
-
|
|
59
|
+
constructor(param0, apiKey) {
|
|
60
|
+
let nodeApi;
|
|
61
|
+
if (typeof param0 === 'string') {
|
|
62
|
+
nodeApi = initializeNodeApi(param0, apiKey);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
nodeApi = param0;
|
|
66
|
+
}
|
|
61
67
|
this.wallets = nodeApi.wallets;
|
|
62
68
|
this.infos = nodeApi.infos;
|
|
63
69
|
this.blockflow = nodeApi.blockflow;
|
|
@@ -69,19 +75,9 @@ class NodeProvider {
|
|
|
69
75
|
this.miners = nodeApi.miners;
|
|
70
76
|
this.events = nodeApi.events;
|
|
71
77
|
}
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
this.wallets = nodeApi.wallets;
|
|
76
|
-
this.infos = nodeApi.infos;
|
|
77
|
-
this.blockflow = nodeApi.blockflow;
|
|
78
|
-
this.addresses = nodeApi.addresses;
|
|
79
|
-
this.transactions = nodeApi.transactions;
|
|
80
|
-
this.contracts = nodeApi.contracts;
|
|
81
|
-
this.multisig = nodeApi.multisig;
|
|
82
|
-
this.utils = nodeApi.utils;
|
|
83
|
-
this.miners = nodeApi.miners;
|
|
84
|
-
this.events = nodeApi.events;
|
|
78
|
+
// This can prevent the proxied node provider from being modified
|
|
79
|
+
static Proxy(nodeProvider) {
|
|
80
|
+
return new NodeProvider(nodeProvider);
|
|
85
81
|
}
|
|
86
82
|
}
|
|
87
83
|
exports.NodeProvider = NodeProvider;
|
|
@@ -90,18 +90,10 @@ export interface SignMessageParams {
|
|
|
90
90
|
export interface SignMessageResult {
|
|
91
91
|
signature: string;
|
|
92
92
|
}
|
|
93
|
-
export
|
|
94
|
-
|
|
95
|
-
signTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult>;
|
|
96
|
-
signDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult>;
|
|
97
|
-
signExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult>;
|
|
98
|
-
signUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult>;
|
|
99
|
-
signHexString(params: SignHexStringParams): Promise<SignHexStringResult>;
|
|
100
|
-
signMessage(params: SignMessageParams): Promise<SignMessageResult>;
|
|
101
|
-
}
|
|
102
|
-
export declare abstract class SignerProvider implements SignerProviderWithoutNodeProvider {
|
|
103
|
-
abstract get nodeProvider(): NodeProvider;
|
|
93
|
+
export declare abstract class SignerProvider {
|
|
94
|
+
abstract get nodeProvider(): NodeProvider | undefined;
|
|
104
95
|
abstract getSelectedAccount(): Promise<Account>;
|
|
96
|
+
private getNodeProvider;
|
|
105
97
|
submitTransaction(unsignedTx: string, signature: string): Promise<SubmissionResult>;
|
|
106
98
|
signAndSubmitTransferTx(params: SignTransferTxParams): Promise<SubmissionResult>;
|
|
107
99
|
signAndSubmitDeployContractTx(params: SignDeployContractTxParams): Promise<SubmissionResult>;
|
|
@@ -131,6 +123,13 @@ export declare abstract class SignerProviderWithMultipleAccounts extends SignerP
|
|
|
131
123
|
getAccount(signerAddress: string): Promise<Account>;
|
|
132
124
|
abstract setSelectedAccount(address: string): Promise<void>;
|
|
133
125
|
}
|
|
126
|
+
export declare class SignerProviderWrapper extends SignerProvider {
|
|
127
|
+
signer: SignerProvider;
|
|
128
|
+
nodeProvider: NodeProvider;
|
|
129
|
+
constructor(signer: SignerProvider, nodeProvider: NodeProvider);
|
|
130
|
+
getSelectedAccount(): Promise<Account>;
|
|
131
|
+
signRaw(signerAddress: string, hexString: string): Promise<string>;
|
|
132
|
+
}
|
|
134
133
|
export interface SubmissionResult {
|
|
135
134
|
txId: string;
|
|
136
135
|
fromGroup: number;
|
|
@@ -43,7 +43,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
43
43
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
44
|
};
|
|
45
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.fromApiDestination = exports.toApiDestinations = exports.toApiDestination = exports.verifySignedMessage = exports.verifyHexString = exports.SignerProviderWithMultipleAccounts = exports.SignerProvider = void 0;
|
|
46
|
+
exports.fromApiDestination = exports.toApiDestinations = exports.toApiDestination = exports.verifySignedMessage = exports.verifyHexString = exports.SignerProviderWrapper = exports.SignerProviderWithMultipleAccounts = exports.SignerProvider = void 0;
|
|
47
47
|
const elliptic_1 = require("elliptic");
|
|
48
48
|
const api_1 = require("../api");
|
|
49
49
|
const utils = __importStar(require("../utils"));
|
|
@@ -63,9 +63,15 @@ const ec = new elliptic_1.ec('secp256k1');
|
|
|
63
63
|
(0, utils_1.assertType)();
|
|
64
64
|
(0, utils_1.assertType)();
|
|
65
65
|
class SignerProvider {
|
|
66
|
+
getNodeProvider() {
|
|
67
|
+
if (this.nodeProvider === undefined) {
|
|
68
|
+
throw Error('The signer does not contain a node provider');
|
|
69
|
+
}
|
|
70
|
+
return this.nodeProvider;
|
|
71
|
+
}
|
|
66
72
|
async submitTransaction(unsignedTx, signature) {
|
|
67
73
|
const params = { unsignedTx: unsignedTx, signature: signature };
|
|
68
|
-
return this.
|
|
74
|
+
return this.getNodeProvider().transactions.postTransactionsSubmit(params);
|
|
69
75
|
}
|
|
70
76
|
async signAndSubmitTransferTx(params) {
|
|
71
77
|
const signResult = await this.signTransferTx(params);
|
|
@@ -103,7 +109,7 @@ class SignerProvider {
|
|
|
103
109
|
destinations: toApiDestinations(params.destinations),
|
|
104
110
|
gasPrice: (0, api_1.toApiNumber256Optional)(params.gasPrice)
|
|
105
111
|
};
|
|
106
|
-
return this.
|
|
112
|
+
return this.getNodeProvider().transactions.postTransactionsBuild(data);
|
|
107
113
|
}
|
|
108
114
|
async signDeployContractTx(params) {
|
|
109
115
|
const response = await this.buildContractCreationTx(params);
|
|
@@ -119,7 +125,7 @@ class SignerProvider {
|
|
|
119
125
|
issueTokenAmount: (0, api_1.toApiNumber256Optional)(params.issueTokenAmount),
|
|
120
126
|
gasPrice: (0, api_1.toApiNumber256Optional)(params.gasPrice)
|
|
121
127
|
};
|
|
122
|
-
return this.
|
|
128
|
+
return this.getNodeProvider().contracts.postContractsUnsignedTxDeployContract(data);
|
|
123
129
|
}
|
|
124
130
|
async signExecuteScriptTx(params) {
|
|
125
131
|
const response = await this.buildScriptTx(params);
|
|
@@ -130,13 +136,13 @@ class SignerProvider {
|
|
|
130
136
|
...(await this.usePublicKey(params)),
|
|
131
137
|
tokens: (0, api_1.toApiTokens)(params.tokens)
|
|
132
138
|
};
|
|
133
|
-
return this.
|
|
139
|
+
return this.getNodeProvider().contracts.postContractsUnsignedTxExecuteScript(data);
|
|
134
140
|
}
|
|
135
141
|
// in general, wallet should show the decoded information to user for confirmation
|
|
136
142
|
// please overwrite this function for real wallet
|
|
137
143
|
async signUnsignedTx(params) {
|
|
138
144
|
const data = { unsignedTx: params.unsignedTx };
|
|
139
|
-
const decoded = await this.
|
|
145
|
+
const decoded = await this.getNodeProvider().transactions.postTransactionsDecodeUnsignedTx(data);
|
|
140
146
|
return this.handleSign({
|
|
141
147
|
fromGroup: decoded.fromGroup,
|
|
142
148
|
toGroup: decoded.toGroup,
|
|
@@ -182,6 +188,20 @@ class SignerProviderWithMultipleAccounts extends SignerProvider {
|
|
|
182
188
|
}
|
|
183
189
|
}
|
|
184
190
|
exports.SignerProviderWithMultipleAccounts = SignerProviderWithMultipleAccounts;
|
|
191
|
+
class SignerProviderWrapper extends SignerProvider {
|
|
192
|
+
constructor(signer, nodeProvider) {
|
|
193
|
+
super();
|
|
194
|
+
this.signer = signer;
|
|
195
|
+
this.nodeProvider = nodeProvider;
|
|
196
|
+
}
|
|
197
|
+
getSelectedAccount() {
|
|
198
|
+
return this.signer.getSelectedAccount();
|
|
199
|
+
}
|
|
200
|
+
signRaw(signerAddress, hexString) {
|
|
201
|
+
return this.signer.signRaw(signerAddress, hexString);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.SignerProviderWrapper = SignerProviderWrapper;
|
|
185
205
|
function verifyHexString(hexString, publicKey, signature) {
|
|
186
206
|
try {
|
|
187
207
|
const key = ec.keyFromPublic(publicKey, 'hex');
|
package/package.json
CHANGED
package/src/api/index.ts
CHANGED
|
@@ -29,20 +29,40 @@ function initializeNodeApi(baseUrl: string, apiKey?: string): NodeApi<string> {
|
|
|
29
29
|
return nodeApi
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
wallets: NodeApi<string>['wallets']
|
|
34
|
-
infos: NodeApi<string>['infos']
|
|
35
|
-
blockflow: NodeApi<string>['blockflow']
|
|
36
|
-
addresses: NodeApi<string>['addresses']
|
|
37
|
-
transactions: NodeApi<string>['transactions']
|
|
38
|
-
contracts: NodeApi<string>['contracts']
|
|
39
|
-
multisig: NodeApi<string>['multisig']
|
|
40
|
-
utils: NodeApi<string>['utils']
|
|
41
|
-
miners: NodeApi<string>['miners']
|
|
42
|
-
events: NodeApi<string>['events']
|
|
32
|
+
interface INodeProvider {
|
|
33
|
+
readonly wallets: NodeApi<string>['wallets']
|
|
34
|
+
readonly infos: NodeApi<string>['infos']
|
|
35
|
+
readonly blockflow: NodeApi<string>['blockflow']
|
|
36
|
+
readonly addresses: NodeApi<string>['addresses']
|
|
37
|
+
readonly transactions: NodeApi<string>['transactions']
|
|
38
|
+
readonly contracts: NodeApi<string>['contracts']
|
|
39
|
+
readonly multisig: NodeApi<string>['multisig']
|
|
40
|
+
readonly utils: NodeApi<string>['utils']
|
|
41
|
+
readonly miners: NodeApi<string>['miners']
|
|
42
|
+
readonly events: NodeApi<string>['events']
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class NodeProvider implements INodeProvider {
|
|
46
|
+
readonly wallets: NodeApi<string>['wallets']
|
|
47
|
+
readonly infos: NodeApi<string>['infos']
|
|
48
|
+
readonly blockflow: NodeApi<string>['blockflow']
|
|
49
|
+
readonly addresses: NodeApi<string>['addresses']
|
|
50
|
+
readonly transactions: NodeApi<string>['transactions']
|
|
51
|
+
readonly contracts: NodeApi<string>['contracts']
|
|
52
|
+
readonly multisig: NodeApi<string>['multisig']
|
|
53
|
+
readonly utils: NodeApi<string>['utils']
|
|
54
|
+
readonly miners: NodeApi<string>['miners']
|
|
55
|
+
readonly events: NodeApi<string>['events']
|
|
43
56
|
|
|
44
|
-
constructor(
|
|
45
|
-
|
|
57
|
+
constructor(provider: INodeProvider)
|
|
58
|
+
constructor(baseUrl: string, apiKey?: string)
|
|
59
|
+
constructor(param0: string | INodeProvider, apiKey?: string) {
|
|
60
|
+
let nodeApi: INodeProvider
|
|
61
|
+
if (typeof param0 === 'string') {
|
|
62
|
+
nodeApi = initializeNodeApi(param0, apiKey)
|
|
63
|
+
} else {
|
|
64
|
+
nodeApi = param0 as INodeProvider
|
|
65
|
+
}
|
|
46
66
|
|
|
47
67
|
this.wallets = nodeApi.wallets
|
|
48
68
|
this.infos = nodeApi.infos
|
|
@@ -56,20 +76,9 @@ export class NodeProvider {
|
|
|
56
76
|
this.events = nodeApi.events
|
|
57
77
|
}
|
|
58
78
|
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.wallets = nodeApi.wallets
|
|
64
|
-
this.infos = nodeApi.infos
|
|
65
|
-
this.blockflow = nodeApi.blockflow
|
|
66
|
-
this.addresses = nodeApi.addresses
|
|
67
|
-
this.transactions = nodeApi.transactions
|
|
68
|
-
this.contracts = nodeApi.contracts
|
|
69
|
-
this.multisig = nodeApi.multisig
|
|
70
|
-
this.utils = nodeApi.utils
|
|
71
|
-
this.miners = nodeApi.miners
|
|
72
|
-
this.events = nodeApi.events
|
|
79
|
+
// This can prevent the proxied node provider from being modified
|
|
80
|
+
static Proxy(nodeProvider: NodeProvider): NodeProvider {
|
|
81
|
+
return new NodeProvider(nodeProvider)
|
|
73
82
|
}
|
|
74
83
|
}
|
|
75
84
|
|
package/src/signer/signer.ts
CHANGED
|
@@ -146,23 +146,20 @@ export interface SignMessageResult {
|
|
|
146
146
|
}
|
|
147
147
|
assertType<Eq<SignMessageResult, Pick<SignResult, 'signature'>>>()
|
|
148
148
|
|
|
149
|
-
export
|
|
150
|
-
|
|
151
|
-
signTransferTx(params: SignTransferTxParams): Promise<SignTransferTxResult>
|
|
152
|
-
signDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult>
|
|
153
|
-
signExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult>
|
|
154
|
-
signUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult>
|
|
155
|
-
signHexString(params: SignHexStringParams): Promise<SignHexStringResult>
|
|
156
|
-
signMessage(params: SignMessageParams): Promise<SignMessageResult>
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export abstract class SignerProvider implements SignerProviderWithoutNodeProvider {
|
|
160
|
-
abstract get nodeProvider(): NodeProvider
|
|
149
|
+
export abstract class SignerProvider {
|
|
150
|
+
abstract get nodeProvider(): NodeProvider | undefined
|
|
161
151
|
abstract getSelectedAccount(): Promise<Account>
|
|
162
152
|
|
|
153
|
+
private getNodeProvider(): NodeProvider {
|
|
154
|
+
if (this.nodeProvider === undefined) {
|
|
155
|
+
throw Error('The signer does not contain a node provider')
|
|
156
|
+
}
|
|
157
|
+
return this.nodeProvider
|
|
158
|
+
}
|
|
159
|
+
|
|
163
160
|
async submitTransaction(unsignedTx: string, signature: string): Promise<SubmissionResult> {
|
|
164
161
|
const params: node.SubmitTransaction = { unsignedTx: unsignedTx, signature: signature }
|
|
165
|
-
return this.
|
|
162
|
+
return this.getNodeProvider().transactions.postTransactionsSubmit(params)
|
|
166
163
|
}
|
|
167
164
|
|
|
168
165
|
async signAndSubmitTransferTx(params: SignTransferTxParams): Promise<SubmissionResult> {
|
|
@@ -205,7 +202,7 @@ export abstract class SignerProvider implements SignerProviderWithoutNodeProvide
|
|
|
205
202
|
destinations: toApiDestinations(params.destinations),
|
|
206
203
|
gasPrice: toApiNumber256Optional(params.gasPrice)
|
|
207
204
|
}
|
|
208
|
-
return this.
|
|
205
|
+
return this.getNodeProvider().transactions.postTransactionsBuild(data)
|
|
209
206
|
}
|
|
210
207
|
|
|
211
208
|
async signDeployContractTx(params: SignDeployContractTxParams): Promise<SignDeployContractTxResult> {
|
|
@@ -223,7 +220,7 @@ export abstract class SignerProvider implements SignerProviderWithoutNodeProvide
|
|
|
223
220
|
issueTokenAmount: toApiNumber256Optional(params.issueTokenAmount),
|
|
224
221
|
gasPrice: toApiNumber256Optional(params.gasPrice)
|
|
225
222
|
}
|
|
226
|
-
return this.
|
|
223
|
+
return this.getNodeProvider().contracts.postContractsUnsignedTxDeployContract(data)
|
|
227
224
|
}
|
|
228
225
|
|
|
229
226
|
async signExecuteScriptTx(params: SignExecuteScriptTxParams): Promise<SignExecuteScriptTxResult> {
|
|
@@ -236,14 +233,14 @@ export abstract class SignerProvider implements SignerProviderWithoutNodeProvide
|
|
|
236
233
|
...(await this.usePublicKey(params)),
|
|
237
234
|
tokens: toApiTokens(params.tokens)
|
|
238
235
|
}
|
|
239
|
-
return this.
|
|
236
|
+
return this.getNodeProvider().contracts.postContractsUnsignedTxExecuteScript(data)
|
|
240
237
|
}
|
|
241
238
|
|
|
242
239
|
// in general, wallet should show the decoded information to user for confirmation
|
|
243
240
|
// please overwrite this function for real wallet
|
|
244
241
|
async signUnsignedTx(params: SignUnsignedTxParams): Promise<SignUnsignedTxResult> {
|
|
245
242
|
const data = { unsignedTx: params.unsignedTx }
|
|
246
|
-
const decoded = await this.
|
|
243
|
+
const decoded = await this.getNodeProvider().transactions.postTransactionsDecodeUnsignedTx(data)
|
|
247
244
|
return this.handleSign({
|
|
248
245
|
fromGroup: decoded.fromGroup,
|
|
249
246
|
toGroup: decoded.toGroup,
|
|
@@ -303,6 +300,25 @@ export abstract class SignerProviderWithMultipleAccounts extends SignerProvider
|
|
|
303
300
|
abstract setSelectedAccount(address: string): Promise<void>
|
|
304
301
|
}
|
|
305
302
|
|
|
303
|
+
export class SignerProviderWrapper extends SignerProvider {
|
|
304
|
+
signer: SignerProvider
|
|
305
|
+
nodeProvider: NodeProvider
|
|
306
|
+
|
|
307
|
+
constructor(signer: SignerProvider, nodeProvider: NodeProvider) {
|
|
308
|
+
super()
|
|
309
|
+
this.signer = signer
|
|
310
|
+
this.nodeProvider = nodeProvider
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
getSelectedAccount(): Promise<Account> {
|
|
314
|
+
return this.signer.getSelectedAccount()
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
signRaw(signerAddress: string, hexString: string): Promise<string> {
|
|
318
|
+
return this.signer.signRaw(signerAddress, hexString)
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
306
322
|
export interface SubmissionResult {
|
|
307
323
|
txId: string
|
|
308
324
|
fromGroup: number
|