@0xsequence/account 1.10.14 → 2.0.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/dist/0xsequence-account.cjs.dev.js +51 -49
- package/dist/0xsequence-account.cjs.prod.js +51 -49
- package/dist/0xsequence-account.esm.js +52 -50
- package/dist/declarations/src/account.d.ts +5 -5
- package/dist/declarations/src/signer.d.ts +19 -17
- package/package.json +15 -12
- package/src/account.ts +40 -32
- package/src/orchestrator/wrapper.ts +5 -5
- package/src/signer.ts +43 -43
- package/src/utils.ts +0 -14
|
@@ -2,7 +2,7 @@ import { walletContracts } from '@0xsequence/abi';
|
|
|
2
2
|
import { commons, universal } from '@0xsequence/core';
|
|
3
3
|
import { defaults, migrator, version } from '@0xsequence/migration';
|
|
4
4
|
import { proto, isRelayer, RpcRelayer } from '@0xsequence/relayer';
|
|
5
|
-
import {
|
|
5
|
+
import { toHexString, getFetchRequest, encodeTypedDataDigest } from '@0xsequence/utils';
|
|
6
6
|
import { Wallet } from '@0xsequence/wallet';
|
|
7
7
|
import { ethers } from 'ethers';
|
|
8
8
|
|
|
@@ -21,20 +21,9 @@ function _extends() {
|
|
|
21
21
|
return _extends.apply(this, arguments);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
function isPromise(value) {
|
|
25
|
-
return !!value && typeof value.then === 'function';
|
|
26
|
-
}
|
|
27
|
-
function isDeferrable(value) {
|
|
28
|
-
// The value is deferrable if any of the properties is a Promises
|
|
29
|
-
if (typeof value === 'object') {
|
|
30
|
-
return Object.keys(value).some(key => isPromise(value[key]));
|
|
31
|
-
}
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
24
|
function encodeGasRefundTransaction(option) {
|
|
36
25
|
if (!option) return [];
|
|
37
|
-
const value =
|
|
26
|
+
const value = BigInt(option.value);
|
|
38
27
|
switch (option.token.type) {
|
|
39
28
|
case proto.FeeTokenType.UNKNOWN:
|
|
40
29
|
return [{
|
|
@@ -42,8 +31,8 @@ function encodeGasRefundTransaction(option) {
|
|
|
42
31
|
revertOnError: true,
|
|
43
32
|
gasLimit: option.gasLimit,
|
|
44
33
|
to: option.to,
|
|
45
|
-
value:
|
|
46
|
-
data:
|
|
34
|
+
value: toHexString(value),
|
|
35
|
+
data: '0x'
|
|
47
36
|
}];
|
|
48
37
|
case proto.FeeTokenType.ERC20_TOKEN:
|
|
49
38
|
if (!option.token.contractAddress) {
|
|
@@ -55,7 +44,7 @@ function encodeGasRefundTransaction(option) {
|
|
|
55
44
|
gasLimit: option.gasLimit,
|
|
56
45
|
to: option.token.contractAddress,
|
|
57
46
|
value: 0,
|
|
58
|
-
data: new ethers.
|
|
47
|
+
data: new ethers.Interface([{
|
|
59
48
|
constant: false,
|
|
60
49
|
inputs: [{
|
|
61
50
|
type: 'address'
|
|
@@ -65,7 +54,7 @@ function encodeGasRefundTransaction(option) {
|
|
|
65
54
|
name: 'transfer',
|
|
66
55
|
outputs: [],
|
|
67
56
|
type: 'function'
|
|
68
|
-
}]).encodeFunctionData('transfer', [option.to,
|
|
57
|
+
}]).encodeFunctionData('transfer', [option.to, toHexString(value)])
|
|
69
58
|
}];
|
|
70
59
|
default:
|
|
71
60
|
throw new Error(`Unhandled fee token type ${option.token.type}`);
|
|
@@ -76,7 +65,6 @@ class AccountSigner {
|
|
|
76
65
|
this.account = account;
|
|
77
66
|
this.chainId = chainId;
|
|
78
67
|
this.options = options;
|
|
79
|
-
this._isSigner = true;
|
|
80
68
|
}
|
|
81
69
|
get provider() {
|
|
82
70
|
return this.account.providerFor(this.chainId);
|
|
@@ -88,6 +76,10 @@ class AccountSigner {
|
|
|
88
76
|
var _this$options$cantVal, _this$options;
|
|
89
77
|
return this.account.signMessage(message, this.chainId, (_this$options$cantVal = (_this$options = this.options) == null ? void 0 : _this$options.cantValidateBehavior) != null ? _this$options$cantVal : 'throw');
|
|
90
78
|
}
|
|
79
|
+
signTypedData(domain, types, value) {
|
|
80
|
+
var _this$options$cantVal2, _this$options2;
|
|
81
|
+
return this.account.signTypedData(domain, types, value, this.chainId, (_this$options$cantVal2 = (_this$options2 = this.options) == null ? void 0 : _this$options2.cantValidateBehavior) != null ? _this$options$cantVal2 : 'throw');
|
|
82
|
+
}
|
|
91
83
|
async defaultSelectFee(_txs, options) {
|
|
92
84
|
// If no options, return undefined
|
|
93
85
|
if (options.length === 0) return undefined;
|
|
@@ -109,33 +101,32 @@ class AccountSigner {
|
|
|
109
101
|
if (option.token.type === proto.FeeTokenType.UNKNOWN) {
|
|
110
102
|
// Native token
|
|
111
103
|
const balance = await this.getBalance();
|
|
112
|
-
if (balance
|
|
104
|
+
if (balance >= BigInt(option.value)) {
|
|
113
105
|
return option;
|
|
114
106
|
}
|
|
115
107
|
} else if (option.token.contractAddress && option.token.type === proto.FeeTokenType.ERC20_TOKEN) {
|
|
116
108
|
// ERC20 token
|
|
117
109
|
const token = new ethers.Contract(option.token.contractAddress, balanceOfAbi, this.provider);
|
|
118
110
|
const balance = await token.balanceOf(this.account.address);
|
|
119
|
-
if (balance
|
|
111
|
+
if (balance >= BigInt(option.value)) {
|
|
120
112
|
return option;
|
|
121
113
|
}
|
|
122
114
|
} else ;
|
|
123
115
|
}
|
|
124
116
|
throw new Error('No fee option available - not enough balance');
|
|
125
117
|
}
|
|
126
|
-
async sendTransaction(
|
|
127
|
-
var _this$options$stubSig, _this$
|
|
128
|
-
const txs = isDeferrable(txsPromise) ? await ethers.utils.resolveProperties(txsPromise) : txsPromise;
|
|
118
|
+
async sendTransaction(txs, options) {
|
|
119
|
+
var _this$options$stubSig, _this$options3, _this$options$selectF, _this$options4, _this$options5;
|
|
129
120
|
const prepare = await this.account.prepareTransactions({
|
|
130
121
|
txs,
|
|
131
122
|
chainId: this.chainId,
|
|
132
|
-
stubSignatureOverrides: (_this$options$stubSig = (_this$
|
|
123
|
+
stubSignatureOverrides: (_this$options$stubSig = (_this$options3 = this.options) == null ? void 0 : _this$options3.stubSignatureOverrides) != null ? _this$options$stubSig : new Map(),
|
|
133
124
|
simulateForFeeOptions: options == null ? void 0 : options.simulateForFeeOptions
|
|
134
125
|
});
|
|
135
|
-
const selectMethod = (_this$options$selectF = (_this$
|
|
126
|
+
const selectMethod = (_this$options$selectF = (_this$options4 = this.options) == null ? void 0 : _this$options4.selectFee) != null ? _this$options$selectF : this.defaultSelectFee.bind(this);
|
|
136
127
|
const feeOption = await selectMethod(txs, prepare.feeOptions);
|
|
137
128
|
const finalTransactions = [...prepare.transactions, ...encodeGasRefundTransaction(feeOption)];
|
|
138
|
-
return this.account.sendTransaction(finalTransactions, this.chainId, prepare.feeQuote, undefined, undefined, ((_this$
|
|
129
|
+
return this.account.sendTransaction(finalTransactions, this.chainId, prepare.feeQuote, undefined, undefined, ((_this$options5 = this.options) == null ? void 0 : _this$options5.nonceSpace) !== undefined ? {
|
|
139
130
|
nonceSpace: this.options.nonceSpace
|
|
140
131
|
} : undefined); // Will always have a transaction response
|
|
141
132
|
}
|
|
@@ -143,7 +134,9 @@ class AccountSigner {
|
|
|
143
134
|
return this.provider.getBalance(this.account.address, blockTag);
|
|
144
135
|
}
|
|
145
136
|
call(transaction, blockTag) {
|
|
146
|
-
return this.provider.call(transaction,
|
|
137
|
+
return this.provider.call(_extends({}, transaction, {
|
|
138
|
+
blockTag
|
|
139
|
+
}));
|
|
147
140
|
}
|
|
148
141
|
async resolveName(name) {
|
|
149
142
|
const res = await this.provider.resolveName(name);
|
|
@@ -163,7 +156,7 @@ class AccountSigner {
|
|
|
163
156
|
throw new Error('Method not implemented.');
|
|
164
157
|
}
|
|
165
158
|
getChainId() {
|
|
166
|
-
return Promise.resolve(
|
|
159
|
+
return Promise.resolve(Number(this.chainId));
|
|
167
160
|
}
|
|
168
161
|
getGasPrice() {
|
|
169
162
|
throw new Error('Method not implemented.');
|
|
@@ -171,10 +164,16 @@ class AccountSigner {
|
|
|
171
164
|
getFeeData() {
|
|
172
165
|
throw new Error('Method not implemented.');
|
|
173
166
|
}
|
|
167
|
+
getNonce(blockTag) {
|
|
168
|
+
throw new Error('Method not implemented.');
|
|
169
|
+
}
|
|
170
|
+
populateCall(tx) {
|
|
171
|
+
throw new Error('Method not implemented.');
|
|
172
|
+
}
|
|
174
173
|
checkTransaction(transaction) {
|
|
175
174
|
throw new Error('Method not implemented.');
|
|
176
175
|
}
|
|
177
|
-
populateTransaction(
|
|
176
|
+
async populateTransaction(tx) {
|
|
178
177
|
throw new Error('Method not implemented.');
|
|
179
178
|
}
|
|
180
179
|
_checkProvider(operation) {
|
|
@@ -193,7 +192,7 @@ class Chain0Reader {
|
|
|
193
192
|
return undefined;
|
|
194
193
|
}
|
|
195
194
|
async nonce(_wallet, _space) {
|
|
196
|
-
return
|
|
195
|
+
return 0n;
|
|
197
196
|
}
|
|
198
197
|
async isValidSignature(_wallet, _digest, _signature) {
|
|
199
198
|
throw new Error('Method not supported.');
|
|
@@ -210,7 +209,7 @@ class Account {
|
|
|
210
209
|
this.orchestrator = void 0;
|
|
211
210
|
this.jwt = void 0;
|
|
212
211
|
this.projectAccessKey = void 0;
|
|
213
|
-
this.address = ethers.
|
|
212
|
+
this.address = ethers.getAddress(options.address);
|
|
214
213
|
this.contexts = options.contexts;
|
|
215
214
|
this.tracker = options.tracker;
|
|
216
215
|
this.networks = options.networks;
|
|
@@ -260,21 +259,25 @@ class Account {
|
|
|
260
259
|
};
|
|
261
260
|
}
|
|
262
261
|
network(chainId) {
|
|
263
|
-
const tcid =
|
|
264
|
-
const found = this.networks.find(n => tcid
|
|
262
|
+
const tcid = BigInt(chainId);
|
|
263
|
+
const found = this.networks.find(n => tcid === BigInt(n.chainId));
|
|
265
264
|
if (!found) throw new Error(`Network not found for chainId ${chainId}`);
|
|
266
265
|
return found;
|
|
267
266
|
}
|
|
268
267
|
providerFor(chainId) {
|
|
269
268
|
const found = this.network(chainId);
|
|
270
|
-
if (!found.provider && !found.rpcUrl)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
if (!found.provider && !found.rpcUrl) {
|
|
270
|
+
throw new Error(`Provider not found for chainId ${chainId}`);
|
|
271
|
+
}
|
|
272
|
+
const network = new ethers.Network(found.name, found.chainId);
|
|
273
|
+
return found.provider || new ethers.JsonRpcProvider(getFetchRequest(found.rpcUrl, this.projectAccessKey, this.jwt), network, {
|
|
274
|
+
staticNetwork: network
|
|
274
275
|
});
|
|
275
276
|
}
|
|
276
277
|
reader(chainId) {
|
|
277
|
-
if (
|
|
278
|
+
if (BigInt(chainId) === 0n) {
|
|
279
|
+
return new Chain0Reader();
|
|
280
|
+
}
|
|
278
281
|
|
|
279
282
|
// TODO: Networks should be able to provide a reader directly
|
|
280
283
|
// and we should default to the on-chain reader
|
|
@@ -306,7 +309,7 @@ class Account {
|
|
|
306
309
|
return this.walletFor(chainId, this.contextFor(status.version), status.config, coder);
|
|
307
310
|
}
|
|
308
311
|
walletFor(chainId, context, config, coders) {
|
|
309
|
-
const isNetworkZero =
|
|
312
|
+
const isNetworkZero = BigInt(chainId) === 0n;
|
|
310
313
|
return new Wallet({
|
|
311
314
|
config,
|
|
312
315
|
context,
|
|
@@ -508,7 +511,7 @@ class Account {
|
|
|
508
511
|
return coder.trim(chainedSignature);
|
|
509
512
|
}
|
|
510
513
|
async publishWitness() {
|
|
511
|
-
const digest = ethers.
|
|
514
|
+
const digest = ethers.id(`This is a Sequence account woo! ${Date.now()}`);
|
|
512
515
|
const signature = await this.signDigest(digest, 0, false);
|
|
513
516
|
const decoded = this.coders.signature.decode(signature);
|
|
514
517
|
const signatures = this.coders.signature.signaturesOfDecoded(decoded);
|
|
@@ -526,7 +529,7 @@ class Account {
|
|
|
526
529
|
// So we ignore the state on "chain zero" and instead use one of the states of the networks
|
|
527
530
|
// wallet-webapp should ensure the wallet is as migrated as possible, trying to mimic
|
|
528
531
|
// the behaviour of being migrated on all chains
|
|
529
|
-
const chainRef =
|
|
532
|
+
const chainRef = BigInt(chainId) === 0n ? this.networks[0].chainId : chainId;
|
|
530
533
|
const status = await this.status(chainRef);
|
|
531
534
|
this.mustBeFullyMigrated(status);
|
|
532
535
|
|
|
@@ -557,11 +560,11 @@ class Account {
|
|
|
557
560
|
}
|
|
558
561
|
buildOnChainSignature(digest) {
|
|
559
562
|
const subdigest = commons.signature.subdigestOf({
|
|
560
|
-
digest: ethers.
|
|
563
|
+
digest: ethers.hexlify(digest),
|
|
561
564
|
chainId: 0,
|
|
562
565
|
address: this.address
|
|
563
566
|
});
|
|
564
|
-
const hexSubdigest = ethers.
|
|
567
|
+
const hexSubdigest = ethers.hexlify(subdigest);
|
|
565
568
|
const config = this.coders.config.fromSimple({
|
|
566
569
|
// Threshold *only* needs to be > 0, this is not a magic number
|
|
567
570
|
// we only use 2 ** 15 because it may lead to lower gas costs in some chains
|
|
@@ -570,7 +573,7 @@ class Account {
|
|
|
570
573
|
signers: [],
|
|
571
574
|
subdigests: [hexSubdigest]
|
|
572
575
|
});
|
|
573
|
-
const walletInterface = new ethers.
|
|
576
|
+
const walletInterface = new ethers.Interface(walletContracts.mainModule.abi);
|
|
574
577
|
const bundle = {
|
|
575
578
|
entrypoint: this.address,
|
|
576
579
|
transactions: [{
|
|
@@ -605,13 +608,13 @@ class Account {
|
|
|
605
608
|
if (bootstrapBundle.transactions.length === 0) {
|
|
606
609
|
throw new Error('Cannot build EIP-6492 signature without bootstrap transactions');
|
|
607
610
|
}
|
|
608
|
-
const encoded = ethers.
|
|
609
|
-
return ethers.
|
|
611
|
+
const encoded = ethers.AbiCoder.defaultAbiCoder().encode(['address', 'bytes', 'bytes'], [bootstrapBundle.entrypoint, commons.transaction.encodeBundleExecData(bootstrapBundle), signature]);
|
|
612
|
+
return ethers.solidityPacked(['bytes', 'bytes32'], [encoded, commons.EIP6492.EIP_6492_SUFFIX]);
|
|
610
613
|
}
|
|
611
614
|
async editConfig(changes) {
|
|
612
615
|
const currentConfig = await this.status(0).then(s => s.config);
|
|
613
616
|
const newConfig = this.coders.config.editConfig(currentConfig, _extends({}, changes, {
|
|
614
|
-
checkpoint: this.coders.config.checkpointOf(currentConfig)
|
|
617
|
+
checkpoint: this.coders.config.checkpointOf(currentConfig) + 1n
|
|
615
618
|
}));
|
|
616
619
|
return this.updateConfig(newConfig);
|
|
617
620
|
}
|
|
@@ -671,7 +674,6 @@ class Account {
|
|
|
671
674
|
const deployTransaction = Wallet.buildDeployTransaction(status.original.context, status.original.imageHash);
|
|
672
675
|
transactions.push(...deployTransaction.transactions);
|
|
673
676
|
}
|
|
674
|
-
transactions.length;
|
|
675
677
|
|
|
676
678
|
// Get pending migrations
|
|
677
679
|
transactions.push(...status.signedMigrations.map(m => ({
|
|
@@ -715,7 +717,7 @@ class Account {
|
|
|
715
717
|
}), feeQuote);
|
|
716
718
|
}
|
|
717
719
|
signMessage(message, chainId, cantValidateBehavior = 'ignore') {
|
|
718
|
-
return this.signDigest(ethers.
|
|
720
|
+
return this.signDigest(ethers.keccak256(message), chainId, true, cantValidateBehavior);
|
|
719
721
|
}
|
|
720
722
|
async signTransactions(txs, chainId, pstatus, options) {
|
|
721
723
|
const status = pstatus || (await this.status(chainId));
|
|
@@ -841,7 +843,7 @@ class Account {
|
|
|
841
843
|
const stubSignature = wallet.coders.config.buildStubSignature(wallet.config, stubSignatureOverrides);
|
|
842
844
|
|
|
843
845
|
// Now we can decorate the transactions as always, but we need to manually build the signed bundle
|
|
844
|
-
const intentId = ethers.
|
|
846
|
+
const intentId = ethers.hexlify(ethers.randomBytes(32));
|
|
845
847
|
const signedBundle = {
|
|
846
848
|
chainId,
|
|
847
849
|
intent: {
|
|
@@ -5,7 +5,7 @@ import { FeeOption, FeeQuote, Relayer } from '@0xsequence/relayer';
|
|
|
5
5
|
import { tracker } from '@0xsequence/sessions';
|
|
6
6
|
import { SignatureOrchestrator } from '@0xsequence/signhub';
|
|
7
7
|
import { Wallet } from '@0xsequence/wallet';
|
|
8
|
-
import { ethers
|
|
8
|
+
import { ethers } from 'ethers';
|
|
9
9
|
import { AccountSigner, AccountSignerOptions } from "./signer.js";
|
|
10
10
|
export type AccountStatus = {
|
|
11
11
|
original: {
|
|
@@ -72,7 +72,7 @@ export declare class Account {
|
|
|
72
72
|
config: commons.config.ConfigCoder;
|
|
73
73
|
};
|
|
74
74
|
network(chainId: ethers.BigNumberish): NetworkConfig;
|
|
75
|
-
providerFor(chainId: ethers.BigNumberish): ethers.
|
|
75
|
+
providerFor(chainId: ethers.BigNumberish): ethers.Provider;
|
|
76
76
|
reader(chainId: ethers.BigNumberish): commons.reader.Reader;
|
|
77
77
|
relayer(chainId: ethers.BigNumberish): Relayer;
|
|
78
78
|
setOrchestrator(orchestrator: SignatureOrchestrator): void;
|
|
@@ -127,7 +127,7 @@ export declare class Account {
|
|
|
127
127
|
migratedAllChains: boolean;
|
|
128
128
|
failedChains: number[];
|
|
129
129
|
}>;
|
|
130
|
-
sendSignedTransactions(signedBundle: commons.transaction.IntendedTransactionBundle | commons.transaction.IntendedTransactionBundle[], chainId: ethers.BigNumberish, quote?: FeeQuote, pstatus?: AccountStatus, callback?: (bundle: commons.transaction.IntendedTransactionBundle) => void): Promise<ethers.
|
|
130
|
+
sendSignedTransactions(signedBundle: commons.transaction.IntendedTransactionBundle | commons.transaction.IntendedTransactionBundle[], chainId: ethers.BigNumberish, quote?: FeeQuote, pstatus?: AccountStatus, callback?: (bundle: commons.transaction.IntendedTransactionBundle) => void): Promise<ethers.TransactionResponse>;
|
|
131
131
|
fillGasLimits(txs: commons.transaction.Transactionish, chainId: ethers.BigNumberish, status?: AccountStatus): Promise<commons.transaction.SimulatedTransaction[]>;
|
|
132
132
|
gasRefundQuotes(txs: commons.transaction.Transactionish, chainId: ethers.BigNumberish, stubSignatureOverrides: Map<string, string>, status?: AccountStatus, options?: {
|
|
133
133
|
simulate?: boolean;
|
|
@@ -145,8 +145,8 @@ export declare class Account {
|
|
|
145
145
|
sendTransaction(txs: commons.transaction.Transactionish, chainId: ethers.BigNumberish, quote?: FeeQuote, skipPreDecorate?: boolean, callback?: (bundle: commons.transaction.IntendedTransactionBundle) => void, options?: {
|
|
146
146
|
nonceSpace?: ethers.BigNumberish;
|
|
147
147
|
serial?: boolean;
|
|
148
|
-
}): Promise<ethers.
|
|
149
|
-
signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, message: Record<string, any>, chainId: ethers.BigNumberish, cantValidateBehavior?: 'ignore' | 'eip6492' | 'throw'): Promise<string>;
|
|
148
|
+
}): Promise<ethers.TransactionResponse | undefined>;
|
|
149
|
+
signTypedData(domain: ethers.TypedDataDomain, types: Record<string, Array<ethers.TypedDataField>>, message: Record<string, any>, chainId: ethers.BigNumberish, cantValidateBehavior?: 'ignore' | 'eip6492' | 'throw'): Promise<string>;
|
|
150
150
|
getSigners(): Promise<Array<{
|
|
151
151
|
address: string;
|
|
152
152
|
network: ChainId;
|
|
@@ -7,32 +7,34 @@ export type AccountSignerOptions = {
|
|
|
7
7
|
nonceSpace?: ethers.BigNumberish;
|
|
8
8
|
cantValidateBehavior?: 'ignore' | 'eip6492' | 'throw';
|
|
9
9
|
stubSignatureOverrides?: Map<string, string>;
|
|
10
|
-
selectFee?: (txs: ethers.
|
|
10
|
+
selectFee?: (txs: ethers.TransactionRequest | commons.transaction.Transactionish, options: FeeOption[]) => Promise<FeeOption | undefined>;
|
|
11
11
|
};
|
|
12
|
-
export declare class AccountSigner implements ethers.
|
|
12
|
+
export declare class AccountSigner implements ethers.AbstractSigner<ethers.Provider> {
|
|
13
13
|
account: Account;
|
|
14
14
|
chainId: ChainId;
|
|
15
15
|
readonly options?: AccountSignerOptions | undefined;
|
|
16
|
-
readonly _isSigner = true;
|
|
17
16
|
constructor(account: Account, chainId: ChainId, options?: AccountSignerOptions | undefined);
|
|
18
|
-
get provider(): ethers.
|
|
17
|
+
get provider(): ethers.Provider;
|
|
19
18
|
getAddress(): Promise<string>;
|
|
20
|
-
signMessage(message: string | ethers.
|
|
19
|
+
signMessage(message: string | ethers.BytesLike): Promise<string>;
|
|
20
|
+
signTypedData(domain: ethers.TypedDataDomain, types: Record<string, Array<ethers.TypedDataField>>, value: Record<string, any>): Promise<string>;
|
|
21
21
|
private defaultSelectFee;
|
|
22
|
-
sendTransaction(
|
|
22
|
+
sendTransaction(txs: commons.transaction.Transactionish, options?: {
|
|
23
23
|
simulateForFeeOptions?: boolean;
|
|
24
|
-
}): Promise<ethers.
|
|
25
|
-
getBalance(blockTag?: ethers.
|
|
26
|
-
call(transaction: ethers.
|
|
24
|
+
}): Promise<ethers.TransactionResponse>;
|
|
25
|
+
getBalance(blockTag?: ethers.BlockTag | undefined): Promise<bigint>;
|
|
26
|
+
call(transaction: ethers.TransactionRequest, blockTag?: ethers.BlockTag): Promise<string>;
|
|
27
27
|
resolveName(name: string): Promise<string>;
|
|
28
|
-
connect(_provider: ethers.
|
|
29
|
-
signTransaction(transaction: ethers.
|
|
30
|
-
getTransactionCount(blockTag?: ethers.
|
|
31
|
-
estimateGas(transaction: ethers.
|
|
28
|
+
connect(_provider: ethers.Provider): ethers.Signer;
|
|
29
|
+
signTransaction(transaction: ethers.TransactionRequest): Promise<string>;
|
|
30
|
+
getTransactionCount(blockTag?: ethers.BlockTag | undefined): Promise<number>;
|
|
31
|
+
estimateGas(transaction: ethers.TransactionRequest): Promise<bigint>;
|
|
32
32
|
getChainId(): Promise<number>;
|
|
33
|
-
getGasPrice(): Promise<
|
|
34
|
-
getFeeData(): Promise<ethers.
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
getGasPrice(): Promise<bigint>;
|
|
34
|
+
getFeeData(): Promise<ethers.FeeData>;
|
|
35
|
+
getNonce(blockTag?: ethers.BlockTag): Promise<number>;
|
|
36
|
+
populateCall(tx: ethers.TransactionRequest): Promise<ethers.TransactionLike<string>>;
|
|
37
|
+
checkTransaction(transaction: ethers.TransactionRequest): ethers.TransactionRequest;
|
|
38
|
+
populateTransaction(tx: ethers.TransactionRequest): Promise<ethers.TransactionLike<string>>;
|
|
37
39
|
_checkProvider(operation?: string | undefined): void;
|
|
38
40
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xsequence/account",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "tools for migrating sequence wallets to new versions",
|
|
5
5
|
"repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/account",
|
|
6
6
|
"source": "src/index.ts",
|
|
@@ -9,21 +9,24 @@
|
|
|
9
9
|
"author": "Horizon Blockchain Games",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"
|
|
13
|
-
"@0xsequence/
|
|
14
|
-
"@0xsequence/
|
|
15
|
-
"@0xsequence/
|
|
16
|
-
"@0xsequence/
|
|
17
|
-
"@0xsequence/
|
|
18
|
-
"@0xsequence/
|
|
19
|
-
"@0xsequence/
|
|
20
|
-
|
|
12
|
+
"@0xsequence/abi": "2.0.0",
|
|
13
|
+
"@0xsequence/core": "2.0.0",
|
|
14
|
+
"@0xsequence/migration": "2.0.0",
|
|
15
|
+
"@0xsequence/network": "2.0.0",
|
|
16
|
+
"@0xsequence/relayer": "2.0.0",
|
|
17
|
+
"@0xsequence/sessions": "2.0.0",
|
|
18
|
+
"@0xsequence/utils": "2.0.0",
|
|
19
|
+
"@0xsequence/wallet": "2.0.0"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"ethers": ">=6"
|
|
21
23
|
},
|
|
22
24
|
"devDependencies": {
|
|
23
25
|
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
|
26
|
+
"ethers": "^6.13.0",
|
|
24
27
|
"nyc": "^15.1.0",
|
|
25
|
-
"@0xsequence/signhub": "
|
|
26
|
-
"@0xsequence/tests": "
|
|
28
|
+
"@0xsequence/signhub": "2.0.0",
|
|
29
|
+
"@0xsequence/tests": "2.0.0"
|
|
27
30
|
},
|
|
28
31
|
"files": [
|
|
29
32
|
"src",
|
package/src/account.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { walletContracts } from '@0xsequence/abi'
|
|
2
2
|
import { commons, universal } from '@0xsequence/core'
|
|
3
|
-
import { WalletSignRequestMetadata } from '@0xsequence/core/src/commons'
|
|
4
3
|
import { migrator, defaults, version } from '@0xsequence/migration'
|
|
5
4
|
import { ChainId, NetworkConfig } from '@0xsequence/network'
|
|
6
5
|
import { FeeOption, FeeQuote, isRelayer, Relayer, RpcRelayer } from '@0xsequence/relayer'
|
|
7
6
|
import { tracker } from '@0xsequence/sessions'
|
|
8
7
|
import { SignatureOrchestrator } from '@0xsequence/signhub'
|
|
9
|
-
import { encodeTypedDataDigest,
|
|
8
|
+
import { encodeTypedDataDigest, getFetchRequest } from '@0xsequence/utils'
|
|
10
9
|
import { Wallet } from '@0xsequence/wallet'
|
|
11
|
-
import { ethers
|
|
10
|
+
import { ethers } from 'ethers'
|
|
12
11
|
import { AccountSigner, AccountSignerOptions } from './signer'
|
|
13
12
|
|
|
14
13
|
export type AccountStatus = {
|
|
@@ -82,11 +81,11 @@ class Chain0Reader implements commons.reader.Reader {
|
|
|
82
81
|
return undefined
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
async nonce(_wallet: string, _space: ethers.BigNumberish): Promise<
|
|
86
|
-
return
|
|
84
|
+
async nonce(_wallet: string, _space: ethers.BigNumberish): Promise<bigint> {
|
|
85
|
+
return 0n
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
async isValidSignature(_wallet: string, _digest: ethers.
|
|
88
|
+
async isValidSignature(_wallet: string, _digest: ethers.BytesLike, _signature: ethers.BytesLike): Promise<boolean> {
|
|
90
89
|
throw new Error('Method not supported.')
|
|
91
90
|
}
|
|
92
91
|
}
|
|
@@ -108,7 +107,7 @@ export class Account {
|
|
|
108
107
|
private projectAccessKey?: string
|
|
109
108
|
|
|
110
109
|
constructor(options: AccountOptions) {
|
|
111
|
-
this.address = ethers.
|
|
110
|
+
this.address = ethers.getAddress(options.address)
|
|
112
111
|
|
|
113
112
|
this.contexts = options.contexts
|
|
114
113
|
this.tracker = options.tracker
|
|
@@ -178,26 +177,32 @@ export class Account {
|
|
|
178
177
|
}
|
|
179
178
|
|
|
180
179
|
network(chainId: ethers.BigNumberish): NetworkConfig {
|
|
181
|
-
const tcid =
|
|
182
|
-
const found = this.networks.find(n => tcid
|
|
180
|
+
const tcid = BigInt(chainId)
|
|
181
|
+
const found = this.networks.find(n => tcid === BigInt(n.chainId))
|
|
183
182
|
if (!found) throw new Error(`Network not found for chainId ${chainId}`)
|
|
184
183
|
return found
|
|
185
184
|
}
|
|
186
185
|
|
|
187
|
-
providerFor(chainId: ethers.BigNumberish): ethers.
|
|
186
|
+
providerFor(chainId: ethers.BigNumberish): ethers.Provider {
|
|
188
187
|
const found = this.network(chainId)
|
|
189
|
-
if (!found.provider && !found.rpcUrl)
|
|
188
|
+
if (!found.provider && !found.rpcUrl) {
|
|
189
|
+
throw new Error(`Provider not found for chainId ${chainId}`)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const network = new ethers.Network(found.name, found.chainId)
|
|
193
|
+
|
|
190
194
|
return (
|
|
191
195
|
found.provider ||
|
|
192
|
-
new ethers.
|
|
193
|
-
|
|
194
|
-
chainId: ethers.BigNumber.from(chainId).toNumber()
|
|
196
|
+
new ethers.JsonRpcProvider(getFetchRequest(found.rpcUrl, this.projectAccessKey, this.jwt), network, {
|
|
197
|
+
staticNetwork: network
|
|
195
198
|
})
|
|
196
199
|
)
|
|
197
200
|
}
|
|
198
201
|
|
|
199
202
|
reader(chainId: ethers.BigNumberish): commons.reader.Reader {
|
|
200
|
-
if (
|
|
203
|
+
if (BigInt(chainId) === 0n) {
|
|
204
|
+
return new Chain0Reader()
|
|
205
|
+
}
|
|
201
206
|
|
|
202
207
|
// TODO: Networks should be able to provide a reader directly
|
|
203
208
|
// and we should default to the on-chain reader
|
|
@@ -241,7 +246,7 @@ export class Account {
|
|
|
241
246
|
config: commons.config.Config,
|
|
242
247
|
coders: typeof this.coders
|
|
243
248
|
): Wallet {
|
|
244
|
-
const isNetworkZero =
|
|
249
|
+
const isNetworkZero = BigInt(chainId) === 0n
|
|
245
250
|
return new Wallet({
|
|
246
251
|
config,
|
|
247
252
|
context,
|
|
@@ -486,7 +491,7 @@ export class Account {
|
|
|
486
491
|
}
|
|
487
492
|
|
|
488
493
|
async publishWitness(): Promise<void> {
|
|
489
|
-
const digest = ethers.
|
|
494
|
+
const digest = ethers.id(`This is a Sequence account woo! ${Date.now()}`)
|
|
490
495
|
const signature = await this.signDigest(digest, 0, false)
|
|
491
496
|
const decoded = this.coders.signature.decode(signature)
|
|
492
497
|
const signatures = this.coders.signature.signaturesOfDecoded(decoded)
|
|
@@ -506,7 +511,7 @@ export class Account {
|
|
|
506
511
|
// So we ignore the state on "chain zero" and instead use one of the states of the networks
|
|
507
512
|
// wallet-webapp should ensure the wallet is as migrated as possible, trying to mimic
|
|
508
513
|
// the behaviour of being migrated on all chains
|
|
509
|
-
const chainRef =
|
|
514
|
+
const chainRef = BigInt(chainId) === 0n ? this.networks[0].chainId : chainId
|
|
510
515
|
const status = await this.status(chainRef)
|
|
511
516
|
this.mustBeFullyMigrated(status)
|
|
512
517
|
|
|
@@ -541,8 +546,12 @@ export class Account {
|
|
|
541
546
|
}
|
|
542
547
|
|
|
543
548
|
buildOnChainSignature(digest: ethers.BytesLike): { bundle: commons.transaction.TransactionBundle; signature: string } {
|
|
544
|
-
const subdigest = commons.signature.subdigestOf({
|
|
545
|
-
|
|
549
|
+
const subdigest = commons.signature.subdigestOf({
|
|
550
|
+
digest: ethers.hexlify(digest),
|
|
551
|
+
chainId: 0,
|
|
552
|
+
address: this.address
|
|
553
|
+
})
|
|
554
|
+
const hexSubdigest = ethers.hexlify(subdigest)
|
|
546
555
|
const config = this.coders.config.fromSimple({
|
|
547
556
|
// Threshold *only* needs to be > 0, this is not a magic number
|
|
548
557
|
// we only use 2 ** 15 because it may lead to lower gas costs in some chains
|
|
@@ -552,7 +561,7 @@ export class Account {
|
|
|
552
561
|
subdigests: [hexSubdigest]
|
|
553
562
|
})
|
|
554
563
|
|
|
555
|
-
const walletInterface = new ethers.
|
|
564
|
+
const walletInterface = new ethers.Interface(walletContracts.mainModule.abi)
|
|
556
565
|
const bundle: commons.transaction.TransactionBundle = {
|
|
557
566
|
entrypoint: this.address,
|
|
558
567
|
transactions: [
|
|
@@ -590,12 +599,12 @@ export class Account {
|
|
|
590
599
|
throw new Error('Cannot build EIP-6492 signature without bootstrap transactions')
|
|
591
600
|
}
|
|
592
601
|
|
|
593
|
-
const encoded = ethers.
|
|
602
|
+
const encoded = ethers.AbiCoder.defaultAbiCoder().encode(
|
|
594
603
|
['address', 'bytes', 'bytes'],
|
|
595
604
|
[bootstrapBundle.entrypoint, commons.transaction.encodeBundleExecData(bootstrapBundle), signature]
|
|
596
605
|
)
|
|
597
606
|
|
|
598
|
-
return ethers.
|
|
607
|
+
return ethers.solidityPacked(['bytes', 'bytes32'], [encoded, commons.EIP6492.EIP_6492_SUFFIX])
|
|
599
608
|
}
|
|
600
609
|
|
|
601
610
|
async editConfig(changes: {
|
|
@@ -606,7 +615,7 @@ export class Account {
|
|
|
606
615
|
const currentConfig = await this.status(0).then(s => s.config)
|
|
607
616
|
const newConfig = this.coders.config.editConfig(currentConfig, {
|
|
608
617
|
...changes,
|
|
609
|
-
checkpoint: this.coders.config.checkpointOf(currentConfig)
|
|
618
|
+
checkpoint: this.coders.config.checkpointOf(currentConfig) + 1n
|
|
610
619
|
})
|
|
611
620
|
|
|
612
621
|
return this.updateConfig(newConfig)
|
|
@@ -671,7 +680,6 @@ export class Account {
|
|
|
671
680
|
|
|
672
681
|
transactions.push(...deployTransaction.transactions)
|
|
673
682
|
}
|
|
674
|
-
const len = transactions.length
|
|
675
683
|
|
|
676
684
|
// Get pending migrations
|
|
677
685
|
transactions.push(
|
|
@@ -718,7 +726,7 @@ export class Account {
|
|
|
718
726
|
chainId: ethers.BigNumberish,
|
|
719
727
|
cantValidateBehavior: 'ignore' | 'eip6492' | 'throw' = 'ignore'
|
|
720
728
|
): Promise<string> {
|
|
721
|
-
return this.signDigest(ethers.
|
|
729
|
+
return this.signDigest(ethers.keccak256(message), chainId, true, cantValidateBehavior)
|
|
722
730
|
}
|
|
723
731
|
|
|
724
732
|
async signTransactions(
|
|
@@ -735,7 +743,7 @@ export class Account {
|
|
|
735
743
|
|
|
736
744
|
const wallet = this.walletForStatus(chainId, status)
|
|
737
745
|
|
|
738
|
-
const metadata: WalletSignRequestMetadata = {
|
|
746
|
+
const metadata: commons.WalletSignRequestMetadata = {
|
|
739
747
|
address: this.address,
|
|
740
748
|
digest: '', // Set in wallet.signTransactions
|
|
741
749
|
chainId,
|
|
@@ -840,7 +848,7 @@ export class Account {
|
|
|
840
848
|
quote?: FeeQuote,
|
|
841
849
|
pstatus?: AccountStatus,
|
|
842
850
|
callback?: (bundle: commons.transaction.IntendedTransactionBundle) => void
|
|
843
|
-
): Promise<ethers.
|
|
851
|
+
): Promise<ethers.TransactionResponse> {
|
|
844
852
|
if (!Array.isArray(signedBundle)) {
|
|
845
853
|
return this.sendSignedTransactions([signedBundle], chainId, quote, pstatus, callback)
|
|
846
854
|
}
|
|
@@ -887,7 +895,7 @@ export class Account {
|
|
|
887
895
|
const stubSignature = wallet.coders.config.buildStubSignature(wallet.config, stubSignatureOverrides)
|
|
888
896
|
|
|
889
897
|
// Now we can decorate the transactions as always, but we need to manually build the signed bundle
|
|
890
|
-
const intentId = ethers.
|
|
898
|
+
const intentId = ethers.hexlify(ethers.randomBytes(32))
|
|
891
899
|
const signedBundle: commons.transaction.SignedTransactionBundle = {
|
|
892
900
|
chainId,
|
|
893
901
|
intent: {
|
|
@@ -938,7 +946,7 @@ export class Account {
|
|
|
938
946
|
nonceSpace?: ethers.BigNumberish
|
|
939
947
|
serial?: boolean
|
|
940
948
|
}
|
|
941
|
-
): Promise<ethers.
|
|
949
|
+
): Promise<ethers.TransactionResponse | undefined> {
|
|
942
950
|
const status = await this.status(chainId)
|
|
943
951
|
|
|
944
952
|
const predecorated = skipPreDecorate ? txs : await this.predecorateTransactions(txs, status, chainId)
|
|
@@ -957,8 +965,8 @@ export class Account {
|
|
|
957
965
|
}
|
|
958
966
|
|
|
959
967
|
async signTypedData(
|
|
960
|
-
domain: TypedDataDomain,
|
|
961
|
-
types: Record<string, Array<TypedDataField>>,
|
|
968
|
+
domain: ethers.TypedDataDomain,
|
|
969
|
+
types: Record<string, Array<ethers.TypedDataField>>,
|
|
962
970
|
message: Record<string, any>,
|
|
963
971
|
chainId: ethers.BigNumberish,
|
|
964
972
|
cantValidateBehavior: 'ignore' | 'eip6492' | 'throw' = 'ignore'
|