@0xsequence/provider 0.0.0-20230726193528 → 0.0.0-20230801185244
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-provider.cjs.dev.js +85 -25
- package/dist/0xsequence-provider.cjs.prod.js +85 -25
- package/dist/0xsequence-provider.esm.js +85 -25
- package/dist/declarations/src/client.d.ts +10 -17
- package/package.json +10 -10
- package/src/client.ts +49 -32
- package/src/provider.ts +24 -3
- package/src/transactions.ts +23 -0
- package/src/transports/wallet-request-handler.ts +5 -0
|
@@ -2107,6 +2107,25 @@ function fromExtended(transaction) {
|
|
|
2107
2107
|
return [transaction, ...(transaction.auxiliary || [])];
|
|
2108
2108
|
}
|
|
2109
2109
|
|
|
2110
|
+
function validateTransactionRequest(wallet, transaction) {
|
|
2111
|
+
const transactions = core.commons.transaction.fromTransactionish(wallet, transaction);
|
|
2112
|
+
const unwound = core.commons.transaction.unwind(wallet, transactions);
|
|
2113
|
+
unwound.forEach(transaction => validateTransaction(wallet, transaction));
|
|
2114
|
+
}
|
|
2115
|
+
function validateTransaction(wallet, transaction) {
|
|
2116
|
+
if (transaction.to.toLowerCase() === wallet.toLowerCase()) {
|
|
2117
|
+
if (transaction.data) {
|
|
2118
|
+
const data = ethers.ethers.utils.arrayify(transaction.data);
|
|
2119
|
+
if (data.length >= 4) {
|
|
2120
|
+
throw new Error('self calls are forbidden');
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
if (transaction.delegateCall) {
|
|
2125
|
+
throw new Error('delegate calls are forbidden');
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2110
2129
|
const SIGNER_READY_TIMEOUT = 10000;
|
|
2111
2130
|
class WalletRequestHandler {
|
|
2112
2131
|
constructor(_account, prompter, networks) {
|
|
@@ -2297,6 +2316,7 @@ class WalletRequestHandler {
|
|
|
2297
2316
|
}
|
|
2298
2317
|
return tx;
|
|
2299
2318
|
});
|
|
2319
|
+
validateTransactionRequest(account.address, transactionParams);
|
|
2300
2320
|
let txnHash = '';
|
|
2301
2321
|
if (_this.prompter === null) {
|
|
2302
2322
|
// prompter is null, so we'll send from here
|
|
@@ -2322,6 +2342,7 @@ class WalletRequestHandler {
|
|
|
2322
2342
|
if (sender !== account.address) {
|
|
2323
2343
|
throw new Error('sender address does not match wallet');
|
|
2324
2344
|
}
|
|
2345
|
+
validateTransactionRequest(account.address, transaction);
|
|
2325
2346
|
if (_this.prompter === null) {
|
|
2326
2347
|
// The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
|
|
2327
2348
|
// this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
|
|
@@ -3101,20 +3122,36 @@ class WalletUtils {
|
|
|
3101
3122
|
|
|
3102
3123
|
class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
3103
3124
|
constructor(client, providerFor, networks = network.allNetworks) {
|
|
3104
|
-
var _this;
|
|
3105
3125
|
// We support a lot of networks
|
|
3106
3126
|
// but we start with the default one
|
|
3107
3127
|
super(client.getChainId());
|
|
3108
|
-
|
|
3128
|
+
|
|
3129
|
+
// Emit events as defined by EIP-1193
|
|
3109
3130
|
this.singleNetworkProviders = {};
|
|
3110
3131
|
this._isSequenceProvider = true;
|
|
3111
3132
|
this.client = client;
|
|
3112
3133
|
this.providerFor = providerFor;
|
|
3113
3134
|
this.networks = networks;
|
|
3114
|
-
client.
|
|
3115
|
-
|
|
3116
|
-
_this.emit('chainChanged', chainId);
|
|
3135
|
+
client.onConnect(details => {
|
|
3136
|
+
this.emit('connect', details);
|
|
3117
3137
|
});
|
|
3138
|
+
client.onDisconnect(error => {
|
|
3139
|
+
this.emit('disconnect', error);
|
|
3140
|
+
});
|
|
3141
|
+
client.onDefaultChainIdChanged(chainId => {
|
|
3142
|
+
this.emit('chainChanged', chainId);
|
|
3143
|
+
});
|
|
3144
|
+
client.onAccountsChanged(accounts => {
|
|
3145
|
+
this.emit('accountsChanged', accounts);
|
|
3146
|
+
});
|
|
3147
|
+
|
|
3148
|
+
// NOTICE: We don't emit 'open' and 'close' events
|
|
3149
|
+
// because these are handled by the library, and they
|
|
3150
|
+
// are not part of EIP-1193
|
|
3151
|
+
|
|
3152
|
+
// devs can still access them using
|
|
3153
|
+
// client.onOpen()
|
|
3154
|
+
// client.onClose()
|
|
3118
3155
|
|
|
3119
3156
|
// Create a Sequence signer too
|
|
3120
3157
|
this.signer = new SequenceSigner(this.client, this);
|
|
@@ -3238,7 +3275,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3238
3275
|
var _provider$prepareRequ;
|
|
3239
3276
|
// First we check if the method should be handled by the client
|
|
3240
3277
|
if (method === 'eth_chainId') {
|
|
3241
|
-
return this.useChainId()
|
|
3278
|
+
return `0x${(await this.useChainId()).toString(16)}`;
|
|
3242
3279
|
}
|
|
3243
3280
|
if (method === 'eth_accounts') {
|
|
3244
3281
|
return [this.client.getAddress()];
|
|
@@ -3549,31 +3586,48 @@ class SequenceClient {
|
|
|
3549
3586
|
this.session = new SequenceClientSession(store);
|
|
3550
3587
|
this.defaultChainId = new DefaultChainIdTracker(store, defaultChainId);
|
|
3551
3588
|
this.transport.on('accountsChanged', accounts => {
|
|
3552
|
-
var _this$callbacks$
|
|
3589
|
+
var _this$callbacks$accou;
|
|
3553
3590
|
if (accounts.length > 1) {
|
|
3554
3591
|
console.warn('SequenceClient: wallet-webapp returned more than one account');
|
|
3555
3592
|
}
|
|
3556
|
-
(_this$callbacks$
|
|
3593
|
+
(_this$callbacks$accou = this.callbacks.accountsChanged) == null ? void 0 : _this$callbacks$accou.forEach(cb => cb(accounts));
|
|
3594
|
+
});
|
|
3595
|
+
this.transport.on('connect', response => {
|
|
3596
|
+
var _this$callbacks$conne;
|
|
3597
|
+
const chainIdHex = ethers.ethers.BigNumber.from(this.getChainId()).toHexString();
|
|
3598
|
+
(_this$callbacks$conne = this.callbacks.connect) == null ? void 0 : _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
|
|
3599
|
+
// Ignore the full connect response
|
|
3600
|
+
// use the chainId defined locally
|
|
3601
|
+
chainId: chainIdHex
|
|
3602
|
+
})));
|
|
3603
|
+
});
|
|
3604
|
+
this.transport.on('disconnect', error => {
|
|
3605
|
+
var _this$callbacks$disco;
|
|
3606
|
+
(_this$callbacks$disco = this.callbacks.disconnect) == null ? void 0 : _this$callbacks$disco.forEach(cb => cb(error));
|
|
3557
3607
|
});
|
|
3558
3608
|
this.transport.on('networks', networks => {
|
|
3559
|
-
var _this$callbacks$
|
|
3560
|
-
(_this$callbacks$
|
|
3609
|
+
var _this$callbacks$netwo;
|
|
3610
|
+
(_this$callbacks$netwo = this.callbacks.networks) == null ? void 0 : _this$callbacks$netwo.forEach(cb => cb(networks));
|
|
3561
3611
|
});
|
|
3562
3612
|
this.transport.on('walletContext', context => {
|
|
3563
|
-
var _this$callbacks$
|
|
3564
|
-
(_this$callbacks$
|
|
3613
|
+
var _this$callbacks$walle;
|
|
3614
|
+
(_this$callbacks$walle = this.callbacks.walletContext) == null ? void 0 : _this$callbacks$walle.forEach(cb => cb(context));
|
|
3565
3615
|
});
|
|
3566
|
-
this.transport.on('open',
|
|
3567
|
-
var _this$callbacks$
|
|
3568
|
-
(_this$callbacks$
|
|
3616
|
+
this.transport.on('open', info => {
|
|
3617
|
+
var _this$callbacks$open;
|
|
3618
|
+
(_this$callbacks$open = this.callbacks.open) == null ? void 0 : _this$callbacks$open.forEach(cb => cb(info));
|
|
3569
3619
|
});
|
|
3570
3620
|
this.transport.on('close', () => {
|
|
3571
|
-
var _this$callbacks$
|
|
3572
|
-
(_this$callbacks$
|
|
3621
|
+
var _this$callbacks$close;
|
|
3622
|
+
(_this$callbacks$close = this.callbacks.close) == null ? void 0 : _this$callbacks$close.forEach(cb => cb());
|
|
3573
3623
|
});
|
|
3624
|
+
|
|
3625
|
+
// We don't listen for the transport chainChanged event
|
|
3626
|
+
// instead we handle it locally, so we listen for changes in the store
|
|
3574
3627
|
this.defaultChainId.onDefaultChainIdChanged(chainId => {
|
|
3575
|
-
var _this$callbacks$
|
|
3576
|
-
|
|
3628
|
+
var _this$callbacks$chain;
|
|
3629
|
+
const chainIdHex = ethers.ethers.BigNumber.from(chainId).toHexString();
|
|
3630
|
+
(_this$callbacks$chain = this.callbacks.chainChanged) == null ? void 0 : _this$callbacks$chain.forEach(cb => cb(chainIdHex));
|
|
3577
3631
|
});
|
|
3578
3632
|
}
|
|
3579
3633
|
|
|
@@ -3592,24 +3646,30 @@ class SequenceClient {
|
|
|
3592
3646
|
// Individual callbacks lead to more idiomatic code
|
|
3593
3647
|
|
|
3594
3648
|
onOpen(callback) {
|
|
3595
|
-
return this.registerCallback('
|
|
3649
|
+
return this.registerCallback('open', callback);
|
|
3596
3650
|
}
|
|
3597
3651
|
onClose(callback) {
|
|
3598
|
-
return this.registerCallback('
|
|
3652
|
+
return this.registerCallback('close', callback);
|
|
3653
|
+
}
|
|
3654
|
+
onConnect(callback) {
|
|
3655
|
+
return this.registerCallback('connect', callback);
|
|
3656
|
+
}
|
|
3657
|
+
onDisconnect(callback) {
|
|
3658
|
+
return this.registerCallback('disconnect', callback);
|
|
3599
3659
|
}
|
|
3600
3660
|
onNetworks(callback) {
|
|
3601
|
-
return this.registerCallback('
|
|
3661
|
+
return this.registerCallback('networks', callback);
|
|
3602
3662
|
}
|
|
3603
3663
|
onAccountsChanged(callback) {
|
|
3604
|
-
return this.registerCallback('
|
|
3664
|
+
return this.registerCallback('accountsChanged', callback);
|
|
3605
3665
|
}
|
|
3606
3666
|
|
|
3607
3667
|
// @deprecated
|
|
3608
3668
|
onWalletContext(callback) {
|
|
3609
|
-
return this.registerCallback('
|
|
3669
|
+
return this.registerCallback('walletContext', callback);
|
|
3610
3670
|
}
|
|
3611
3671
|
onDefaultChainIdChanged(callback) {
|
|
3612
|
-
return this.registerCallback('
|
|
3672
|
+
return this.registerCallback('chainChanged', callback);
|
|
3613
3673
|
}
|
|
3614
3674
|
getChainId() {
|
|
3615
3675
|
return this.defaultChainId.getDefaultChainId();
|
|
@@ -2107,6 +2107,25 @@ function fromExtended(transaction) {
|
|
|
2107
2107
|
return [transaction, ...(transaction.auxiliary || [])];
|
|
2108
2108
|
}
|
|
2109
2109
|
|
|
2110
|
+
function validateTransactionRequest(wallet, transaction) {
|
|
2111
|
+
const transactions = core.commons.transaction.fromTransactionish(wallet, transaction);
|
|
2112
|
+
const unwound = core.commons.transaction.unwind(wallet, transactions);
|
|
2113
|
+
unwound.forEach(transaction => validateTransaction(wallet, transaction));
|
|
2114
|
+
}
|
|
2115
|
+
function validateTransaction(wallet, transaction) {
|
|
2116
|
+
if (transaction.to.toLowerCase() === wallet.toLowerCase()) {
|
|
2117
|
+
if (transaction.data) {
|
|
2118
|
+
const data = ethers.ethers.utils.arrayify(transaction.data);
|
|
2119
|
+
if (data.length >= 4) {
|
|
2120
|
+
throw new Error('self calls are forbidden');
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
if (transaction.delegateCall) {
|
|
2125
|
+
throw new Error('delegate calls are forbidden');
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2110
2129
|
const SIGNER_READY_TIMEOUT = 10000;
|
|
2111
2130
|
class WalletRequestHandler {
|
|
2112
2131
|
constructor(_account, prompter, networks) {
|
|
@@ -2297,6 +2316,7 @@ class WalletRequestHandler {
|
|
|
2297
2316
|
}
|
|
2298
2317
|
return tx;
|
|
2299
2318
|
});
|
|
2319
|
+
validateTransactionRequest(account.address, transactionParams);
|
|
2300
2320
|
let txnHash = '';
|
|
2301
2321
|
if (_this.prompter === null) {
|
|
2302
2322
|
// prompter is null, so we'll send from here
|
|
@@ -2322,6 +2342,7 @@ class WalletRequestHandler {
|
|
|
2322
2342
|
if (sender !== account.address) {
|
|
2323
2343
|
throw new Error('sender address does not match wallet');
|
|
2324
2344
|
}
|
|
2345
|
+
validateTransactionRequest(account.address, transaction);
|
|
2325
2346
|
if (_this.prompter === null) {
|
|
2326
2347
|
// The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
|
|
2327
2348
|
// this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
|
|
@@ -3101,20 +3122,36 @@ class WalletUtils {
|
|
|
3101
3122
|
|
|
3102
3123
|
class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
3103
3124
|
constructor(client, providerFor, networks = network.allNetworks) {
|
|
3104
|
-
var _this;
|
|
3105
3125
|
// We support a lot of networks
|
|
3106
3126
|
// but we start with the default one
|
|
3107
3127
|
super(client.getChainId());
|
|
3108
|
-
|
|
3128
|
+
|
|
3129
|
+
// Emit events as defined by EIP-1193
|
|
3109
3130
|
this.singleNetworkProviders = {};
|
|
3110
3131
|
this._isSequenceProvider = true;
|
|
3111
3132
|
this.client = client;
|
|
3112
3133
|
this.providerFor = providerFor;
|
|
3113
3134
|
this.networks = networks;
|
|
3114
|
-
client.
|
|
3115
|
-
|
|
3116
|
-
_this.emit('chainChanged', chainId);
|
|
3135
|
+
client.onConnect(details => {
|
|
3136
|
+
this.emit('connect', details);
|
|
3117
3137
|
});
|
|
3138
|
+
client.onDisconnect(error => {
|
|
3139
|
+
this.emit('disconnect', error);
|
|
3140
|
+
});
|
|
3141
|
+
client.onDefaultChainIdChanged(chainId => {
|
|
3142
|
+
this.emit('chainChanged', chainId);
|
|
3143
|
+
});
|
|
3144
|
+
client.onAccountsChanged(accounts => {
|
|
3145
|
+
this.emit('accountsChanged', accounts);
|
|
3146
|
+
});
|
|
3147
|
+
|
|
3148
|
+
// NOTICE: We don't emit 'open' and 'close' events
|
|
3149
|
+
// because these are handled by the library, and they
|
|
3150
|
+
// are not part of EIP-1193
|
|
3151
|
+
|
|
3152
|
+
// devs can still access them using
|
|
3153
|
+
// client.onOpen()
|
|
3154
|
+
// client.onClose()
|
|
3118
3155
|
|
|
3119
3156
|
// Create a Sequence signer too
|
|
3120
3157
|
this.signer = new SequenceSigner(this.client, this);
|
|
@@ -3238,7 +3275,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3238
3275
|
var _provider$prepareRequ;
|
|
3239
3276
|
// First we check if the method should be handled by the client
|
|
3240
3277
|
if (method === 'eth_chainId') {
|
|
3241
|
-
return this.useChainId()
|
|
3278
|
+
return `0x${(await this.useChainId()).toString(16)}`;
|
|
3242
3279
|
}
|
|
3243
3280
|
if (method === 'eth_accounts') {
|
|
3244
3281
|
return [this.client.getAddress()];
|
|
@@ -3549,31 +3586,48 @@ class SequenceClient {
|
|
|
3549
3586
|
this.session = new SequenceClientSession(store);
|
|
3550
3587
|
this.defaultChainId = new DefaultChainIdTracker(store, defaultChainId);
|
|
3551
3588
|
this.transport.on('accountsChanged', accounts => {
|
|
3552
|
-
var _this$callbacks$
|
|
3589
|
+
var _this$callbacks$accou;
|
|
3553
3590
|
if (accounts.length > 1) {
|
|
3554
3591
|
console.warn('SequenceClient: wallet-webapp returned more than one account');
|
|
3555
3592
|
}
|
|
3556
|
-
(_this$callbacks$
|
|
3593
|
+
(_this$callbacks$accou = this.callbacks.accountsChanged) == null ? void 0 : _this$callbacks$accou.forEach(cb => cb(accounts));
|
|
3594
|
+
});
|
|
3595
|
+
this.transport.on('connect', response => {
|
|
3596
|
+
var _this$callbacks$conne;
|
|
3597
|
+
const chainIdHex = ethers.ethers.BigNumber.from(this.getChainId()).toHexString();
|
|
3598
|
+
(_this$callbacks$conne = this.callbacks.connect) == null ? void 0 : _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
|
|
3599
|
+
// Ignore the full connect response
|
|
3600
|
+
// use the chainId defined locally
|
|
3601
|
+
chainId: chainIdHex
|
|
3602
|
+
})));
|
|
3603
|
+
});
|
|
3604
|
+
this.transport.on('disconnect', error => {
|
|
3605
|
+
var _this$callbacks$disco;
|
|
3606
|
+
(_this$callbacks$disco = this.callbacks.disconnect) == null ? void 0 : _this$callbacks$disco.forEach(cb => cb(error));
|
|
3557
3607
|
});
|
|
3558
3608
|
this.transport.on('networks', networks => {
|
|
3559
|
-
var _this$callbacks$
|
|
3560
|
-
(_this$callbacks$
|
|
3609
|
+
var _this$callbacks$netwo;
|
|
3610
|
+
(_this$callbacks$netwo = this.callbacks.networks) == null ? void 0 : _this$callbacks$netwo.forEach(cb => cb(networks));
|
|
3561
3611
|
});
|
|
3562
3612
|
this.transport.on('walletContext', context => {
|
|
3563
|
-
var _this$callbacks$
|
|
3564
|
-
(_this$callbacks$
|
|
3613
|
+
var _this$callbacks$walle;
|
|
3614
|
+
(_this$callbacks$walle = this.callbacks.walletContext) == null ? void 0 : _this$callbacks$walle.forEach(cb => cb(context));
|
|
3565
3615
|
});
|
|
3566
|
-
this.transport.on('open',
|
|
3567
|
-
var _this$callbacks$
|
|
3568
|
-
(_this$callbacks$
|
|
3616
|
+
this.transport.on('open', info => {
|
|
3617
|
+
var _this$callbacks$open;
|
|
3618
|
+
(_this$callbacks$open = this.callbacks.open) == null ? void 0 : _this$callbacks$open.forEach(cb => cb(info));
|
|
3569
3619
|
});
|
|
3570
3620
|
this.transport.on('close', () => {
|
|
3571
|
-
var _this$callbacks$
|
|
3572
|
-
(_this$callbacks$
|
|
3621
|
+
var _this$callbacks$close;
|
|
3622
|
+
(_this$callbacks$close = this.callbacks.close) == null ? void 0 : _this$callbacks$close.forEach(cb => cb());
|
|
3573
3623
|
});
|
|
3624
|
+
|
|
3625
|
+
// We don't listen for the transport chainChanged event
|
|
3626
|
+
// instead we handle it locally, so we listen for changes in the store
|
|
3574
3627
|
this.defaultChainId.onDefaultChainIdChanged(chainId => {
|
|
3575
|
-
var _this$callbacks$
|
|
3576
|
-
|
|
3628
|
+
var _this$callbacks$chain;
|
|
3629
|
+
const chainIdHex = ethers.ethers.BigNumber.from(chainId).toHexString();
|
|
3630
|
+
(_this$callbacks$chain = this.callbacks.chainChanged) == null ? void 0 : _this$callbacks$chain.forEach(cb => cb(chainIdHex));
|
|
3577
3631
|
});
|
|
3578
3632
|
}
|
|
3579
3633
|
|
|
@@ -3592,24 +3646,30 @@ class SequenceClient {
|
|
|
3592
3646
|
// Individual callbacks lead to more idiomatic code
|
|
3593
3647
|
|
|
3594
3648
|
onOpen(callback) {
|
|
3595
|
-
return this.registerCallback('
|
|
3649
|
+
return this.registerCallback('open', callback);
|
|
3596
3650
|
}
|
|
3597
3651
|
onClose(callback) {
|
|
3598
|
-
return this.registerCallback('
|
|
3652
|
+
return this.registerCallback('close', callback);
|
|
3653
|
+
}
|
|
3654
|
+
onConnect(callback) {
|
|
3655
|
+
return this.registerCallback('connect', callback);
|
|
3656
|
+
}
|
|
3657
|
+
onDisconnect(callback) {
|
|
3658
|
+
return this.registerCallback('disconnect', callback);
|
|
3599
3659
|
}
|
|
3600
3660
|
onNetworks(callback) {
|
|
3601
|
-
return this.registerCallback('
|
|
3661
|
+
return this.registerCallback('networks', callback);
|
|
3602
3662
|
}
|
|
3603
3663
|
onAccountsChanged(callback) {
|
|
3604
|
-
return this.registerCallback('
|
|
3664
|
+
return this.registerCallback('accountsChanged', callback);
|
|
3605
3665
|
}
|
|
3606
3666
|
|
|
3607
3667
|
// @deprecated
|
|
3608
3668
|
onWalletContext(callback) {
|
|
3609
|
-
return this.registerCallback('
|
|
3669
|
+
return this.registerCallback('walletContext', callback);
|
|
3610
3670
|
}
|
|
3611
3671
|
onDefaultChainIdChanged(callback) {
|
|
3612
|
-
return this.registerCallback('
|
|
3672
|
+
return this.registerCallback('chainChanged', callback);
|
|
3613
3673
|
}
|
|
3614
3674
|
getChainId() {
|
|
3615
3675
|
return this.defaultChainId.getDefaultChainId();
|
|
@@ -2103,6 +2103,25 @@ function fromExtended(transaction) {
|
|
|
2103
2103
|
return [transaction, ...(transaction.auxiliary || [])];
|
|
2104
2104
|
}
|
|
2105
2105
|
|
|
2106
|
+
function validateTransactionRequest(wallet, transaction) {
|
|
2107
|
+
const transactions = commons.transaction.fromTransactionish(wallet, transaction);
|
|
2108
|
+
const unwound = commons.transaction.unwind(wallet, transactions);
|
|
2109
|
+
unwound.forEach(transaction => validateTransaction(wallet, transaction));
|
|
2110
|
+
}
|
|
2111
|
+
function validateTransaction(wallet, transaction) {
|
|
2112
|
+
if (transaction.to.toLowerCase() === wallet.toLowerCase()) {
|
|
2113
|
+
if (transaction.data) {
|
|
2114
|
+
const data = ethers.utils.arrayify(transaction.data);
|
|
2115
|
+
if (data.length >= 4) {
|
|
2116
|
+
throw new Error('self calls are forbidden');
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
if (transaction.delegateCall) {
|
|
2121
|
+
throw new Error('delegate calls are forbidden');
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2106
2125
|
const SIGNER_READY_TIMEOUT = 10000;
|
|
2107
2126
|
class WalletRequestHandler {
|
|
2108
2127
|
constructor(_account, prompter, networks) {
|
|
@@ -2293,6 +2312,7 @@ class WalletRequestHandler {
|
|
|
2293
2312
|
}
|
|
2294
2313
|
return tx;
|
|
2295
2314
|
});
|
|
2315
|
+
validateTransactionRequest(account.address, transactionParams);
|
|
2296
2316
|
let txnHash = '';
|
|
2297
2317
|
if (_this.prompter === null) {
|
|
2298
2318
|
// prompter is null, so we'll send from here
|
|
@@ -2318,6 +2338,7 @@ class WalletRequestHandler {
|
|
|
2318
2338
|
if (sender !== account.address) {
|
|
2319
2339
|
throw new Error('sender address does not match wallet');
|
|
2320
2340
|
}
|
|
2341
|
+
validateTransactionRequest(account.address, transaction);
|
|
2321
2342
|
if (_this.prompter === null) {
|
|
2322
2343
|
// The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
|
|
2323
2344
|
// this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
|
|
@@ -3097,20 +3118,36 @@ class WalletUtils {
|
|
|
3097
3118
|
|
|
3098
3119
|
class SequenceProvider extends ethers.providers.BaseProvider {
|
|
3099
3120
|
constructor(client, providerFor, networks = allNetworks) {
|
|
3100
|
-
var _this;
|
|
3101
3121
|
// We support a lot of networks
|
|
3102
3122
|
// but we start with the default one
|
|
3103
3123
|
super(client.getChainId());
|
|
3104
|
-
|
|
3124
|
+
|
|
3125
|
+
// Emit events as defined by EIP-1193
|
|
3105
3126
|
this.singleNetworkProviders = {};
|
|
3106
3127
|
this._isSequenceProvider = true;
|
|
3107
3128
|
this.client = client;
|
|
3108
3129
|
this.providerFor = providerFor;
|
|
3109
3130
|
this.networks = networks;
|
|
3110
|
-
client.
|
|
3111
|
-
|
|
3112
|
-
_this.emit('chainChanged', chainId);
|
|
3131
|
+
client.onConnect(details => {
|
|
3132
|
+
this.emit('connect', details);
|
|
3113
3133
|
});
|
|
3134
|
+
client.onDisconnect(error => {
|
|
3135
|
+
this.emit('disconnect', error);
|
|
3136
|
+
});
|
|
3137
|
+
client.onDefaultChainIdChanged(chainId => {
|
|
3138
|
+
this.emit('chainChanged', chainId);
|
|
3139
|
+
});
|
|
3140
|
+
client.onAccountsChanged(accounts => {
|
|
3141
|
+
this.emit('accountsChanged', accounts);
|
|
3142
|
+
});
|
|
3143
|
+
|
|
3144
|
+
// NOTICE: We don't emit 'open' and 'close' events
|
|
3145
|
+
// because these are handled by the library, and they
|
|
3146
|
+
// are not part of EIP-1193
|
|
3147
|
+
|
|
3148
|
+
// devs can still access them using
|
|
3149
|
+
// client.onOpen()
|
|
3150
|
+
// client.onClose()
|
|
3114
3151
|
|
|
3115
3152
|
// Create a Sequence signer too
|
|
3116
3153
|
this.signer = new SequenceSigner(this.client, this);
|
|
@@ -3234,7 +3271,7 @@ class SequenceProvider extends ethers.providers.BaseProvider {
|
|
|
3234
3271
|
var _provider$prepareRequ;
|
|
3235
3272
|
// First we check if the method should be handled by the client
|
|
3236
3273
|
if (method === 'eth_chainId') {
|
|
3237
|
-
return this.useChainId()
|
|
3274
|
+
return `0x${(await this.useChainId()).toString(16)}`;
|
|
3238
3275
|
}
|
|
3239
3276
|
if (method === 'eth_accounts') {
|
|
3240
3277
|
return [this.client.getAddress()];
|
|
@@ -3545,31 +3582,48 @@ class SequenceClient {
|
|
|
3545
3582
|
this.session = new SequenceClientSession(store);
|
|
3546
3583
|
this.defaultChainId = new DefaultChainIdTracker(store, defaultChainId);
|
|
3547
3584
|
this.transport.on('accountsChanged', accounts => {
|
|
3548
|
-
var _this$callbacks$
|
|
3585
|
+
var _this$callbacks$accou;
|
|
3549
3586
|
if (accounts.length > 1) {
|
|
3550
3587
|
console.warn('SequenceClient: wallet-webapp returned more than one account');
|
|
3551
3588
|
}
|
|
3552
|
-
(_this$callbacks$
|
|
3589
|
+
(_this$callbacks$accou = this.callbacks.accountsChanged) == null ? void 0 : _this$callbacks$accou.forEach(cb => cb(accounts));
|
|
3590
|
+
});
|
|
3591
|
+
this.transport.on('connect', response => {
|
|
3592
|
+
var _this$callbacks$conne;
|
|
3593
|
+
const chainIdHex = ethers.BigNumber.from(this.getChainId()).toHexString();
|
|
3594
|
+
(_this$callbacks$conne = this.callbacks.connect) == null ? void 0 : _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
|
|
3595
|
+
// Ignore the full connect response
|
|
3596
|
+
// use the chainId defined locally
|
|
3597
|
+
chainId: chainIdHex
|
|
3598
|
+
})));
|
|
3599
|
+
});
|
|
3600
|
+
this.transport.on('disconnect', error => {
|
|
3601
|
+
var _this$callbacks$disco;
|
|
3602
|
+
(_this$callbacks$disco = this.callbacks.disconnect) == null ? void 0 : _this$callbacks$disco.forEach(cb => cb(error));
|
|
3553
3603
|
});
|
|
3554
3604
|
this.transport.on('networks', networks => {
|
|
3555
|
-
var _this$callbacks$
|
|
3556
|
-
(_this$callbacks$
|
|
3605
|
+
var _this$callbacks$netwo;
|
|
3606
|
+
(_this$callbacks$netwo = this.callbacks.networks) == null ? void 0 : _this$callbacks$netwo.forEach(cb => cb(networks));
|
|
3557
3607
|
});
|
|
3558
3608
|
this.transport.on('walletContext', context => {
|
|
3559
|
-
var _this$callbacks$
|
|
3560
|
-
(_this$callbacks$
|
|
3609
|
+
var _this$callbacks$walle;
|
|
3610
|
+
(_this$callbacks$walle = this.callbacks.walletContext) == null ? void 0 : _this$callbacks$walle.forEach(cb => cb(context));
|
|
3561
3611
|
});
|
|
3562
|
-
this.transport.on('open',
|
|
3563
|
-
var _this$callbacks$
|
|
3564
|
-
(_this$callbacks$
|
|
3612
|
+
this.transport.on('open', info => {
|
|
3613
|
+
var _this$callbacks$open;
|
|
3614
|
+
(_this$callbacks$open = this.callbacks.open) == null ? void 0 : _this$callbacks$open.forEach(cb => cb(info));
|
|
3565
3615
|
});
|
|
3566
3616
|
this.transport.on('close', () => {
|
|
3567
|
-
var _this$callbacks$
|
|
3568
|
-
(_this$callbacks$
|
|
3617
|
+
var _this$callbacks$close;
|
|
3618
|
+
(_this$callbacks$close = this.callbacks.close) == null ? void 0 : _this$callbacks$close.forEach(cb => cb());
|
|
3569
3619
|
});
|
|
3620
|
+
|
|
3621
|
+
// We don't listen for the transport chainChanged event
|
|
3622
|
+
// instead we handle it locally, so we listen for changes in the store
|
|
3570
3623
|
this.defaultChainId.onDefaultChainIdChanged(chainId => {
|
|
3571
|
-
var _this$callbacks$
|
|
3572
|
-
|
|
3624
|
+
var _this$callbacks$chain;
|
|
3625
|
+
const chainIdHex = ethers.BigNumber.from(chainId).toHexString();
|
|
3626
|
+
(_this$callbacks$chain = this.callbacks.chainChanged) == null ? void 0 : _this$callbacks$chain.forEach(cb => cb(chainIdHex));
|
|
3573
3627
|
});
|
|
3574
3628
|
}
|
|
3575
3629
|
|
|
@@ -3588,24 +3642,30 @@ class SequenceClient {
|
|
|
3588
3642
|
// Individual callbacks lead to more idiomatic code
|
|
3589
3643
|
|
|
3590
3644
|
onOpen(callback) {
|
|
3591
|
-
return this.registerCallback('
|
|
3645
|
+
return this.registerCallback('open', callback);
|
|
3592
3646
|
}
|
|
3593
3647
|
onClose(callback) {
|
|
3594
|
-
return this.registerCallback('
|
|
3648
|
+
return this.registerCallback('close', callback);
|
|
3649
|
+
}
|
|
3650
|
+
onConnect(callback) {
|
|
3651
|
+
return this.registerCallback('connect', callback);
|
|
3652
|
+
}
|
|
3653
|
+
onDisconnect(callback) {
|
|
3654
|
+
return this.registerCallback('disconnect', callback);
|
|
3595
3655
|
}
|
|
3596
3656
|
onNetworks(callback) {
|
|
3597
|
-
return this.registerCallback('
|
|
3657
|
+
return this.registerCallback('networks', callback);
|
|
3598
3658
|
}
|
|
3599
3659
|
onAccountsChanged(callback) {
|
|
3600
|
-
return this.registerCallback('
|
|
3660
|
+
return this.registerCallback('accountsChanged', callback);
|
|
3601
3661
|
}
|
|
3602
3662
|
|
|
3603
3663
|
// @deprecated
|
|
3604
3664
|
onWalletContext(callback) {
|
|
3605
|
-
return this.registerCallback('
|
|
3665
|
+
return this.registerCallback('walletContext', callback);
|
|
3606
3666
|
}
|
|
3607
3667
|
onDefaultChainIdChanged(callback) {
|
|
3608
|
-
return this.registerCallback('
|
|
3668
|
+
return this.registerCallback('chainChanged', callback);
|
|
3609
3669
|
}
|
|
3610
3670
|
getChainId() {
|
|
3611
3671
|
return this.defaultChainId.getDefaultChainId();
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import { JsonRpcRequest, NetworkConfig } from "@0xsequence/network";
|
|
2
|
-
import { ConnectDetails, ConnectOptions, ItemStore, MuxTransportTemplate, OpenWalletIntent, OptionalChainId, OptionalEIP6492, ProviderTransport, WalletSession } from "./index.js";
|
|
2
|
+
import { ConnectDetails, ConnectOptions, ItemStore, MuxTransportTemplate, OpenWalletIntent, OptionalChainId, OptionalEIP6492, ProviderTransport, WalletEventTypes, WalletSession } from "./index.js";
|
|
3
3
|
import { commons } from "@0xsequence/core";
|
|
4
4
|
import { TypedData } from "@0xsequence/utils";
|
|
5
5
|
import { ethers } from "ethers";
|
|
6
|
-
type Callbacks = {
|
|
7
|
-
onOpen: () => void;
|
|
8
|
-
onClose: () => void;
|
|
9
|
-
onNetworks: (networks: NetworkConfig[]) => void;
|
|
10
|
-
onAccountsChanged: (accounts: string[]) => void;
|
|
11
|
-
onWalletContext: (context: commons.context.VersionedContext) => void;
|
|
12
|
-
onDefaultChainIdChanged: (chainId: number) => void;
|
|
13
|
-
};
|
|
14
6
|
/**
|
|
15
7
|
* This session class is meant to persist the state of the wallet connection
|
|
16
8
|
* whitin the dapp. This enables the client to retain the wallet address (and some more)
|
|
@@ -53,13 +45,15 @@ export declare class SequenceClient {
|
|
|
53
45
|
private readonly callbacks;
|
|
54
46
|
readonly transport: ProviderTransport;
|
|
55
47
|
constructor(transport: ProviderTransport | MuxTransportTemplate, store: ItemStore, defaultChainId?: number);
|
|
56
|
-
registerCallback<K extends keyof
|
|
57
|
-
onOpen(callback:
|
|
58
|
-
onClose(callback:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
registerCallback<K extends keyof WalletEventTypes>(eventName: K, callback: WalletEventTypes[K]): () => void;
|
|
49
|
+
onOpen(callback: WalletEventTypes['open']): () => void;
|
|
50
|
+
onClose(callback: WalletEventTypes['close']): () => void;
|
|
51
|
+
onConnect(callback: WalletEventTypes['connect']): () => void;
|
|
52
|
+
onDisconnect(callback: WalletEventTypes['disconnect']): () => void;
|
|
53
|
+
onNetworks(callback: WalletEventTypes['networks']): () => void;
|
|
54
|
+
onAccountsChanged(callback: WalletEventTypes['accountsChanged']): () => void;
|
|
55
|
+
onWalletContext(callback: WalletEventTypes['walletContext']): () => void;
|
|
56
|
+
onDefaultChainIdChanged(callback: WalletEventTypes['chainChanged']): () => void;
|
|
63
57
|
getChainId(): number;
|
|
64
58
|
setDefaultChainId(chainId: number): void;
|
|
65
59
|
openWallet(path?: string, intent?: OpenWalletIntent): Promise<boolean>;
|
|
@@ -78,4 +72,3 @@ export declare class SequenceClient {
|
|
|
78
72
|
getWalletContext(): Promise<commons.context.VersionedContext>;
|
|
79
73
|
getOnchainWalletConfig(options?: OptionalChainId): Promise<commons.config.Config>;
|
|
80
74
|
}
|
|
81
|
-
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xsequence/provider",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-20230801185244",
|
|
4
4
|
"description": "provider sub-package for Sequence",
|
|
5
5
|
"repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/provider",
|
|
6
6
|
"source": "src/index.ts",
|
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"eventemitter2": "^6.4.5",
|
|
13
13
|
"webextension-polyfill": "^0.10.0",
|
|
14
|
-
"@0xsequence/
|
|
15
|
-
"@0xsequence/
|
|
16
|
-
"@0xsequence/
|
|
17
|
-
"@0xsequence/auth": "0.0.0-
|
|
18
|
-
"@0xsequence/
|
|
19
|
-
"@0xsequence/network": "0.0.0-
|
|
20
|
-
"@0xsequence/relayer": "0.0.0-
|
|
21
|
-
"@0xsequence/utils": "0.0.0-
|
|
22
|
-
"@0xsequence/wallet": "0.0.0-
|
|
14
|
+
"@0xsequence/account": "0.0.0-20230801185244",
|
|
15
|
+
"@0xsequence/abi": "0.0.0-20230801185244",
|
|
16
|
+
"@0xsequence/core": "0.0.0-20230801185244",
|
|
17
|
+
"@0xsequence/auth": "0.0.0-20230801185244",
|
|
18
|
+
"@0xsequence/migration": "0.0.0-20230801185244",
|
|
19
|
+
"@0xsequence/network": "0.0.0-20230801185244",
|
|
20
|
+
"@0xsequence/relayer": "0.0.0-20230801185244",
|
|
21
|
+
"@0xsequence/utils": "0.0.0-20230801185244",
|
|
22
|
+
"@0xsequence/wallet": "0.0.0-20230801185244"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"ethers": ">=5.5 < 6"
|
package/src/client.ts
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import { JsonRpcRequest, JsonRpcResponse, NetworkConfig } from "@0xsequence/network"
|
|
2
|
-
import { ConnectDetails, ConnectOptions, ItemStore, MuxMessageProvider, MuxTransportTemplate, OpenWalletIntent, OptionalChainId, OptionalEIP6492, ProviderTransport, WalletSession, isMuxTransportTemplate, isProviderTransport } from "."
|
|
2
|
+
import { ConnectDetails, ConnectOptions, ItemStore, MuxMessageProvider, MuxTransportTemplate, OpenWalletIntent, OptionalChainId, OptionalEIP6492, ProviderTransport, WalletEventTypes, WalletSession, isMuxTransportTemplate, isProviderTransport } from "."
|
|
3
3
|
import { commons } from "@0xsequence/core"
|
|
4
4
|
import { TypedData } from "@0xsequence/utils"
|
|
5
5
|
import { toExtended } from "./extended"
|
|
6
6
|
import { ethers } from "ethers"
|
|
7
7
|
|
|
8
|
-
type Callbacks = {
|
|
9
|
-
onOpen: () => void
|
|
10
|
-
onClose: () => void
|
|
11
|
-
onNetworks: (networks: NetworkConfig[]) => void
|
|
12
|
-
onAccountsChanged: (accounts: string[]) => void
|
|
13
|
-
onWalletContext: (context: commons.context.VersionedContext) => void
|
|
14
|
-
onDefaultChainIdChanged: (chainId: number) => void
|
|
15
|
-
}
|
|
16
8
|
|
|
17
9
|
/**
|
|
18
10
|
* This session class is meant to persist the state of the wallet connection
|
|
@@ -123,7 +115,7 @@ export class DefaultChainIdTracker {
|
|
|
123
115
|
export class SequenceClient {
|
|
124
116
|
private readonly session: SequenceClientSession
|
|
125
117
|
private readonly defaultChainId: DefaultChainIdTracker
|
|
126
|
-
private readonly callbacks: { [K in keyof
|
|
118
|
+
private readonly callbacks: { [K in keyof WalletEventTypes]?: WalletEventTypes[K][] } = {}
|
|
127
119
|
|
|
128
120
|
public readonly transport: ProviderTransport
|
|
129
121
|
|
|
@@ -148,33 +140,50 @@ export class SequenceClient {
|
|
|
148
140
|
console.warn('SequenceClient: wallet-webapp returned more than one account')
|
|
149
141
|
}
|
|
150
142
|
|
|
151
|
-
this.callbacks.
|
|
143
|
+
this.callbacks.accountsChanged?.forEach(cb => cb(accounts))
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
this.transport.on('connect', (response: ConnectDetails) => {
|
|
147
|
+
const chainIdHex = ethers.BigNumber.from(this.getChainId()).toHexString()
|
|
148
|
+
this.callbacks.connect?.forEach(cb => cb({
|
|
149
|
+
...response,
|
|
150
|
+
// Ignore the full connect response
|
|
151
|
+
// use the chainId defined locally
|
|
152
|
+
chainId: chainIdHex
|
|
153
|
+
}))
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
this.transport.on('disconnect', (error) => {
|
|
157
|
+
this.callbacks.disconnect?.forEach(cb => cb(error))
|
|
152
158
|
})
|
|
153
159
|
|
|
154
|
-
this.transport.on('networks', (networks
|
|
155
|
-
this.callbacks.
|
|
160
|
+
this.transport.on('networks', (networks) => {
|
|
161
|
+
this.callbacks.networks?.forEach(cb => cb(networks))
|
|
156
162
|
})
|
|
157
163
|
|
|
158
|
-
this.transport.on('walletContext', (context
|
|
159
|
-
this.callbacks.
|
|
164
|
+
this.transport.on('walletContext', (context) => {
|
|
165
|
+
this.callbacks.walletContext?.forEach(cb => cb(context))
|
|
160
166
|
})
|
|
161
167
|
|
|
162
|
-
this.transport.on('open', () => {
|
|
163
|
-
this.callbacks.
|
|
168
|
+
this.transport.on('open', (info) => {
|
|
169
|
+
this.callbacks.open?.forEach(cb => cb(info))
|
|
164
170
|
})
|
|
165
171
|
|
|
166
172
|
this.transport.on('close', () => {
|
|
167
|
-
this.callbacks.
|
|
173
|
+
this.callbacks.close?.forEach(cb => cb())
|
|
168
174
|
})
|
|
169
175
|
|
|
176
|
+
// We don't listen for the transport chainChanged event
|
|
177
|
+
// instead we handle it locally, so we listen for changes in the store
|
|
170
178
|
this.defaultChainId.onDefaultChainIdChanged((chainId: number) => {
|
|
171
|
-
|
|
179
|
+
const chainIdHex = ethers.BigNumber.from(chainId).toHexString()
|
|
180
|
+
this.callbacks.chainChanged?.forEach(cb => cb(chainIdHex))
|
|
172
181
|
})
|
|
173
182
|
}
|
|
174
183
|
|
|
175
184
|
// Callbacks
|
|
176
185
|
|
|
177
|
-
registerCallback<K extends keyof
|
|
186
|
+
registerCallback<K extends keyof WalletEventTypes>(eventName: K, callback: WalletEventTypes[K]) {
|
|
178
187
|
if (!this.callbacks[eventName]) {
|
|
179
188
|
this.callbacks[eventName] = []
|
|
180
189
|
}
|
|
@@ -188,29 +197,37 @@ export class SequenceClient {
|
|
|
188
197
|
|
|
189
198
|
// Individual callbacks lead to more idiomatic code
|
|
190
199
|
|
|
191
|
-
onOpen(callback:
|
|
192
|
-
return this.registerCallback('
|
|
200
|
+
onOpen(callback: WalletEventTypes['open']) {
|
|
201
|
+
return this.registerCallback('open', callback)
|
|
193
202
|
}
|
|
194
203
|
|
|
195
|
-
onClose(callback:
|
|
196
|
-
return this.registerCallback('
|
|
204
|
+
onClose(callback: WalletEventTypes['close']) {
|
|
205
|
+
return this.registerCallback('close', callback)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
onConnect(callback: WalletEventTypes['connect']) {
|
|
209
|
+
return this.registerCallback('connect', callback)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
onDisconnect(callback: WalletEventTypes['disconnect']) {
|
|
213
|
+
return this.registerCallback('disconnect', callback)
|
|
197
214
|
}
|
|
198
215
|
|
|
199
|
-
onNetworks(callback:
|
|
200
|
-
return this.registerCallback('
|
|
216
|
+
onNetworks(callback: WalletEventTypes['networks']) {
|
|
217
|
+
return this.registerCallback('networks', callback)
|
|
201
218
|
}
|
|
202
219
|
|
|
203
|
-
onAccountsChanged(callback:
|
|
204
|
-
return this.registerCallback('
|
|
220
|
+
onAccountsChanged(callback: WalletEventTypes['accountsChanged']) {
|
|
221
|
+
return this.registerCallback('accountsChanged', callback)
|
|
205
222
|
}
|
|
206
223
|
|
|
207
224
|
// @deprecated
|
|
208
|
-
onWalletContext(callback:
|
|
209
|
-
return this.registerCallback('
|
|
225
|
+
onWalletContext(callback: WalletEventTypes['walletContext']) {
|
|
226
|
+
return this.registerCallback('walletContext', callback)
|
|
210
227
|
}
|
|
211
228
|
|
|
212
|
-
onDefaultChainIdChanged(callback:
|
|
213
|
-
return this.registerCallback('
|
|
229
|
+
onDefaultChainIdChanged(callback: WalletEventTypes['chainChanged']) {
|
|
230
|
+
return this.registerCallback('chainChanged', callback)
|
|
214
231
|
}
|
|
215
232
|
|
|
216
233
|
getChainId(): number {
|
package/src/provider.ts
CHANGED
|
@@ -63,11 +63,32 @@ export class SequenceProvider extends ethers.providers.BaseProvider implements I
|
|
|
63
63
|
// We support a lot of networks
|
|
64
64
|
// but we start with the default one
|
|
65
65
|
super(client.getChainId())
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
|
|
67
|
+
// Emit events as defined by EIP-1193
|
|
68
|
+
client.onConnect((details) => {
|
|
69
|
+
this.emit('connect', details)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
client.onDisconnect((error) => {
|
|
73
|
+
this.emit('disconnect', error)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
client.onDefaultChainIdChanged((chainId) => {
|
|
68
77
|
this.emit('chainChanged', chainId)
|
|
69
78
|
})
|
|
70
79
|
|
|
80
|
+
client.onAccountsChanged((accounts) => {
|
|
81
|
+
this.emit('accountsChanged', accounts)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// NOTICE: We don't emit 'open' and 'close' events
|
|
85
|
+
// because these are handled by the library, and they
|
|
86
|
+
// are not part of EIP-1193
|
|
87
|
+
|
|
88
|
+
// devs can still access them using
|
|
89
|
+
// client.onOpen()
|
|
90
|
+
// client.onClose()
|
|
91
|
+
|
|
71
92
|
// Create a Sequence signer too
|
|
72
93
|
this.signer = new SequenceSigner(this.client, this)
|
|
73
94
|
|
|
@@ -226,7 +247,7 @@ export class SequenceProvider extends ethers.providers.BaseProvider implements I
|
|
|
226
247
|
async perform(method: string, params: any): Promise<any> {
|
|
227
248
|
// First we check if the method should be handled by the client
|
|
228
249
|
if (method === 'eth_chainId') {
|
|
229
|
-
return this.useChainId()
|
|
250
|
+
return `0x${(await this.useChainId()).toString(16)}`
|
|
230
251
|
}
|
|
231
252
|
|
|
232
253
|
if (method === 'eth_accounts') {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { commons } from '@0xsequence/core'
|
|
2
|
+
import { ethers } from 'ethers'
|
|
3
|
+
|
|
4
|
+
export function validateTransactionRequest(wallet: string, transaction: commons.transaction.Transactionish) {
|
|
5
|
+
const transactions = commons.transaction.fromTransactionish(wallet, transaction)
|
|
6
|
+
const unwound = commons.transaction.unwind(wallet, transactions)
|
|
7
|
+
unwound.forEach(transaction => validateTransaction(wallet, transaction))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function validateTransaction(wallet: string, transaction: commons.transaction.Transaction) {
|
|
11
|
+
if (transaction.to.toLowerCase() === wallet.toLowerCase()) {
|
|
12
|
+
if (transaction.data) {
|
|
13
|
+
const data = ethers.utils.arrayify(transaction.data)
|
|
14
|
+
if (data.length >= 4) {
|
|
15
|
+
throw new Error('self calls are forbidden')
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (transaction.delegateCall) {
|
|
21
|
+
throw new Error('delegate calls are forbidden')
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -7,6 +7,7 @@ import { BigNumber, ethers, providers } from 'ethers'
|
|
|
7
7
|
import { EventEmitter2 as EventEmitter } from 'eventemitter2'
|
|
8
8
|
|
|
9
9
|
import { fromExtended } from '../extended'
|
|
10
|
+
import { validateTransactionRequest } from '../transactions'
|
|
10
11
|
import {
|
|
11
12
|
ProviderMessageRequest,
|
|
12
13
|
ProviderMessageResponse,
|
|
@@ -393,6 +394,8 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
|
|
|
393
394
|
return tx
|
|
394
395
|
})
|
|
395
396
|
|
|
397
|
+
validateTransactionRequest(account.address, transactionParams)
|
|
398
|
+
|
|
396
399
|
let txnHash = ''
|
|
397
400
|
if (this.prompter === null) {
|
|
398
401
|
// prompter is null, so we'll send from here
|
|
@@ -421,6 +424,8 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
|
|
|
421
424
|
throw new Error('sender address does not match wallet')
|
|
422
425
|
}
|
|
423
426
|
|
|
427
|
+
validateTransactionRequest(account.address, transaction)
|
|
428
|
+
|
|
424
429
|
if (this.prompter === null) {
|
|
425
430
|
// The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
|
|
426
431
|
// this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
|