@0xsequence/provider 0.42.8 → 0.42.10
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 +128 -3
- package/dist/0xsequence-provider.cjs.prod.js +128 -3
- package/dist/0xsequence-provider.esm.js +128 -3
- package/dist/declarations/src/eip191exceptions.d.ts +3 -0
- package/dist/declarations/src/transports/wallet-request-handler.d.ts +5 -1
- package/dist/declarations/src/types.d.ts +1 -1
- package/package.json +11 -10
- package/src/eip191exceptions.ts +137 -0
- package/src/provider.ts +1 -1
- package/src/transports/wallet-request-handler.ts +14 -0
- package/src/types.ts +1 -2
- package/src/utils/index.ts +7 -1
- package/src/utils.ts +6 -1
|
@@ -483,12 +483,13 @@ class WalletRequestHandler {
|
|
|
483
483
|
// signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
|
|
484
484
|
// value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
|
|
485
485
|
// a Signer value is the actually interface to a signed-in account
|
|
486
|
-
constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
|
|
486
|
+
constructor(_signer, prompter, auxDataProvider, mainnetNetworks, testnetNetworks = []) {
|
|
487
487
|
var _this = this;
|
|
488
488
|
|
|
489
489
|
this.signer = void 0;
|
|
490
490
|
this.signerReadyCallbacks = [];
|
|
491
491
|
this.prompter = void 0;
|
|
492
|
+
this.auxDataProvider = void 0;
|
|
492
493
|
this.mainnetNetworks = void 0;
|
|
493
494
|
this.testnetNetworks = void 0;
|
|
494
495
|
this._openIntent = void 0;
|
|
@@ -962,6 +963,7 @@ class WalletRequestHandler {
|
|
|
962
963
|
|
|
963
964
|
this.signer = _signer;
|
|
964
965
|
this.prompter = prompter;
|
|
966
|
+
this.auxDataProvider = auxDataProvider;
|
|
965
967
|
this.mainnetNetworks = mainnetNetworks;
|
|
966
968
|
this.testnetNetworks = testnetNetworks;
|
|
967
969
|
}
|
|
@@ -1055,6 +1057,16 @@ class WalletRequestHandler {
|
|
|
1055
1057
|
chainId: ethers.ethers.utils.hexlify(await this.getChainId())
|
|
1056
1058
|
};
|
|
1057
1059
|
|
|
1060
|
+
if (options && options.askForEmail) {
|
|
1061
|
+
var _this$auxDataProvider;
|
|
1062
|
+
|
|
1063
|
+
const email = await ((_this$auxDataProvider = this.auxDataProvider) == null ? void 0 : _this$auxDataProvider.get('email'));
|
|
1064
|
+
|
|
1065
|
+
if (email) {
|
|
1066
|
+
connectDetails.email = email;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1058
1070
|
if (options && options.authorize) {
|
|
1059
1071
|
// Perform ethauth eip712 request and construct the ConnectDetails response
|
|
1060
1072
|
// including the auth proof
|
|
@@ -1339,7 +1351,7 @@ function isSequenceProvider(provider) {
|
|
|
1339
1351
|
}
|
|
1340
1352
|
class LocalWeb3Provider extends Web3Provider {
|
|
1341
1353
|
constructor(signer, networks) {
|
|
1342
|
-
const walletRequestHandler = new WalletRequestHandler(signer, null, networks || []);
|
|
1354
|
+
const walletRequestHandler = new WalletRequestHandler(signer, null, null, networks || []);
|
|
1343
1355
|
super(walletRequestHandler);
|
|
1344
1356
|
}
|
|
1345
1357
|
|
|
@@ -1719,6 +1731,114 @@ const hexlifyTransaction = (transaction, allowExtra) => {
|
|
|
1719
1731
|
return result;
|
|
1720
1732
|
};
|
|
1721
1733
|
|
|
1734
|
+
function messageIsExemptFromEIP191Prefix(message) {
|
|
1735
|
+
return EIP_191_PREFIX_EXCEPTIONS.some(e => e.predicate(message));
|
|
1736
|
+
}
|
|
1737
|
+
const EIP_191_PREFIX_EXCEPTIONS = [// NOTE: Decentraland does not support 191 correctly.
|
|
1738
|
+
{
|
|
1739
|
+
name: 'Decentraland Exception',
|
|
1740
|
+
predicate: isDecentralandLoginMessage
|
|
1741
|
+
}, // NOTE: 0x v3 does not support 191 correctly.
|
|
1742
|
+
// See https://gov.0x.org/t/zeip-proposal-fix-v3-eip-191-non-compliance-when-validating-eip-1271-signatures/3396 for more info.
|
|
1743
|
+
{
|
|
1744
|
+
name: '0x v3 Exception',
|
|
1745
|
+
predicate: isZeroExV3Order
|
|
1746
|
+
}];
|
|
1747
|
+
const DCL_REGEX = /^Decentraland Login\nEphemeral address: 0x[a-fA-F0-9]{40}\nExpiration: (\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)((-(\d{2}):(\d{2})|Z)?)$/;
|
|
1748
|
+
function isDecentralandLoginMessage(bytes) {
|
|
1749
|
+
try {
|
|
1750
|
+
const stringified = ethers.ethers.utils.toUtf8String(bytes);
|
|
1751
|
+
return DCL_REGEX.test(stringified);
|
|
1752
|
+
} catch (_unused) {
|
|
1753
|
+
return false;
|
|
1754
|
+
}
|
|
1755
|
+
} // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
|
|
1756
|
+
// see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
|
|
1757
|
+
|
|
1758
|
+
function isZeroExV3Order(bytes) {
|
|
1759
|
+
const abi = new ethers.ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
|
|
1760
|
+
|
|
1761
|
+
try {
|
|
1762
|
+
abi.decodeFunctionData('OrderWithHash', bytes);
|
|
1763
|
+
return true;
|
|
1764
|
+
} catch (err) {
|
|
1765
|
+
// failed to decode ABI, so it's not a v3 order.
|
|
1766
|
+
return false;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
const ZeroXV3EIP1271OrderWithHashAbi = [{
|
|
1770
|
+
inputs: [{
|
|
1771
|
+
components: [{
|
|
1772
|
+
internalType: 'address',
|
|
1773
|
+
name: 'makerAddress',
|
|
1774
|
+
type: 'address'
|
|
1775
|
+
}, {
|
|
1776
|
+
internalType: 'address',
|
|
1777
|
+
name: 'takerAddress',
|
|
1778
|
+
type: 'address'
|
|
1779
|
+
}, {
|
|
1780
|
+
internalType: 'address',
|
|
1781
|
+
name: 'feeRecipientAddress',
|
|
1782
|
+
type: 'address'
|
|
1783
|
+
}, {
|
|
1784
|
+
internalType: 'address',
|
|
1785
|
+
name: 'senderAddress',
|
|
1786
|
+
type: 'address'
|
|
1787
|
+
}, {
|
|
1788
|
+
internalType: 'uint256',
|
|
1789
|
+
name: 'makerAssetAmount',
|
|
1790
|
+
type: 'uint256'
|
|
1791
|
+
}, {
|
|
1792
|
+
internalType: 'uint256',
|
|
1793
|
+
name: 'takerAssetAmount',
|
|
1794
|
+
type: 'uint256'
|
|
1795
|
+
}, {
|
|
1796
|
+
internalType: 'uint256',
|
|
1797
|
+
name: 'makerFee',
|
|
1798
|
+
type: 'uint256'
|
|
1799
|
+
}, {
|
|
1800
|
+
internalType: 'uint256',
|
|
1801
|
+
name: 'takerFee',
|
|
1802
|
+
type: 'uint256'
|
|
1803
|
+
}, {
|
|
1804
|
+
internalType: 'uint256',
|
|
1805
|
+
name: 'expirationTimeSeconds',
|
|
1806
|
+
type: 'uint256'
|
|
1807
|
+
}, {
|
|
1808
|
+
internalType: 'uint256',
|
|
1809
|
+
name: 'salt',
|
|
1810
|
+
type: 'uint256'
|
|
1811
|
+
}, {
|
|
1812
|
+
internalType: 'bytes',
|
|
1813
|
+
name: 'makerAssetData',
|
|
1814
|
+
type: 'bytes'
|
|
1815
|
+
}, {
|
|
1816
|
+
internalType: 'bytes',
|
|
1817
|
+
name: 'takerAssetData',
|
|
1818
|
+
type: 'bytes'
|
|
1819
|
+
}, {
|
|
1820
|
+
internalType: 'bytes',
|
|
1821
|
+
name: 'makerFeeAssetData',
|
|
1822
|
+
type: 'bytes'
|
|
1823
|
+
}, {
|
|
1824
|
+
internalType: 'bytes',
|
|
1825
|
+
name: 'takerFeeAssetData',
|
|
1826
|
+
type: 'bytes'
|
|
1827
|
+
}],
|
|
1828
|
+
internalType: 'struct IEIP1271Data.Order',
|
|
1829
|
+
name: 'order',
|
|
1830
|
+
type: 'tuple'
|
|
1831
|
+
}, {
|
|
1832
|
+
internalType: 'bytes32',
|
|
1833
|
+
name: 'orderHash',
|
|
1834
|
+
type: 'bytes32'
|
|
1835
|
+
}],
|
|
1836
|
+
name: 'OrderWithHash',
|
|
1837
|
+
outputs: [],
|
|
1838
|
+
stateMutability: 'pure',
|
|
1839
|
+
type: 'function'
|
|
1840
|
+
}];
|
|
1841
|
+
|
|
1722
1842
|
const eip191prefix = ethers.ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
|
|
1723
1843
|
const messageToBytes = message => {
|
|
1724
1844
|
if (ethers.ethers.utils.isBytes(message) || ethers.ethers.utils.isHexString(message)) {
|
|
@@ -1729,7 +1849,12 @@ const messageToBytes = message => {
|
|
|
1729
1849
|
};
|
|
1730
1850
|
const prefixEIP191Message = message => {
|
|
1731
1851
|
const messageBytes = messageToBytes(message);
|
|
1732
|
-
|
|
1852
|
+
|
|
1853
|
+
if (messageIsExemptFromEIP191Prefix(messageBytes)) {
|
|
1854
|
+
return messageBytes;
|
|
1855
|
+
} else {
|
|
1856
|
+
return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
|
|
1857
|
+
}
|
|
1733
1858
|
};
|
|
1734
1859
|
const isValidSignature = async (address, digest, sig, provider, chainId, walletContext) => {
|
|
1735
1860
|
if (!chainId) {
|
|
@@ -483,12 +483,13 @@ class WalletRequestHandler {
|
|
|
483
483
|
// signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
|
|
484
484
|
// value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
|
|
485
485
|
// a Signer value is the actually interface to a signed-in account
|
|
486
|
-
constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
|
|
486
|
+
constructor(_signer, prompter, auxDataProvider, mainnetNetworks, testnetNetworks = []) {
|
|
487
487
|
var _this = this;
|
|
488
488
|
|
|
489
489
|
this.signer = void 0;
|
|
490
490
|
this.signerReadyCallbacks = [];
|
|
491
491
|
this.prompter = void 0;
|
|
492
|
+
this.auxDataProvider = void 0;
|
|
492
493
|
this.mainnetNetworks = void 0;
|
|
493
494
|
this.testnetNetworks = void 0;
|
|
494
495
|
this._openIntent = void 0;
|
|
@@ -962,6 +963,7 @@ class WalletRequestHandler {
|
|
|
962
963
|
|
|
963
964
|
this.signer = _signer;
|
|
964
965
|
this.prompter = prompter;
|
|
966
|
+
this.auxDataProvider = auxDataProvider;
|
|
965
967
|
this.mainnetNetworks = mainnetNetworks;
|
|
966
968
|
this.testnetNetworks = testnetNetworks;
|
|
967
969
|
}
|
|
@@ -1055,6 +1057,16 @@ class WalletRequestHandler {
|
|
|
1055
1057
|
chainId: ethers.ethers.utils.hexlify(await this.getChainId())
|
|
1056
1058
|
};
|
|
1057
1059
|
|
|
1060
|
+
if (options && options.askForEmail) {
|
|
1061
|
+
var _this$auxDataProvider;
|
|
1062
|
+
|
|
1063
|
+
const email = await ((_this$auxDataProvider = this.auxDataProvider) == null ? void 0 : _this$auxDataProvider.get('email'));
|
|
1064
|
+
|
|
1065
|
+
if (email) {
|
|
1066
|
+
connectDetails.email = email;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1058
1070
|
if (options && options.authorize) {
|
|
1059
1071
|
// Perform ethauth eip712 request and construct the ConnectDetails response
|
|
1060
1072
|
// including the auth proof
|
|
@@ -1339,7 +1351,7 @@ function isSequenceProvider(provider) {
|
|
|
1339
1351
|
}
|
|
1340
1352
|
class LocalWeb3Provider extends Web3Provider {
|
|
1341
1353
|
constructor(signer, networks) {
|
|
1342
|
-
const walletRequestHandler = new WalletRequestHandler(signer, null, networks || []);
|
|
1354
|
+
const walletRequestHandler = new WalletRequestHandler(signer, null, null, networks || []);
|
|
1343
1355
|
super(walletRequestHandler);
|
|
1344
1356
|
}
|
|
1345
1357
|
|
|
@@ -1719,6 +1731,114 @@ const hexlifyTransaction = (transaction, allowExtra) => {
|
|
|
1719
1731
|
return result;
|
|
1720
1732
|
};
|
|
1721
1733
|
|
|
1734
|
+
function messageIsExemptFromEIP191Prefix(message) {
|
|
1735
|
+
return EIP_191_PREFIX_EXCEPTIONS.some(e => e.predicate(message));
|
|
1736
|
+
}
|
|
1737
|
+
const EIP_191_PREFIX_EXCEPTIONS = [// NOTE: Decentraland does not support 191 correctly.
|
|
1738
|
+
{
|
|
1739
|
+
name: 'Decentraland Exception',
|
|
1740
|
+
predicate: isDecentralandLoginMessage
|
|
1741
|
+
}, // NOTE: 0x v3 does not support 191 correctly.
|
|
1742
|
+
// See https://gov.0x.org/t/zeip-proposal-fix-v3-eip-191-non-compliance-when-validating-eip-1271-signatures/3396 for more info.
|
|
1743
|
+
{
|
|
1744
|
+
name: '0x v3 Exception',
|
|
1745
|
+
predicate: isZeroExV3Order
|
|
1746
|
+
}];
|
|
1747
|
+
const DCL_REGEX = /^Decentraland Login\nEphemeral address: 0x[a-fA-F0-9]{40}\nExpiration: (\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)((-(\d{2}):(\d{2})|Z)?)$/;
|
|
1748
|
+
function isDecentralandLoginMessage(bytes) {
|
|
1749
|
+
try {
|
|
1750
|
+
const stringified = ethers.ethers.utils.toUtf8String(bytes);
|
|
1751
|
+
return DCL_REGEX.test(stringified);
|
|
1752
|
+
} catch (_unused) {
|
|
1753
|
+
return false;
|
|
1754
|
+
}
|
|
1755
|
+
} // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
|
|
1756
|
+
// see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
|
|
1757
|
+
|
|
1758
|
+
function isZeroExV3Order(bytes) {
|
|
1759
|
+
const abi = new ethers.ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
|
|
1760
|
+
|
|
1761
|
+
try {
|
|
1762
|
+
abi.decodeFunctionData('OrderWithHash', bytes);
|
|
1763
|
+
return true;
|
|
1764
|
+
} catch (err) {
|
|
1765
|
+
// failed to decode ABI, so it's not a v3 order.
|
|
1766
|
+
return false;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
const ZeroXV3EIP1271OrderWithHashAbi = [{
|
|
1770
|
+
inputs: [{
|
|
1771
|
+
components: [{
|
|
1772
|
+
internalType: 'address',
|
|
1773
|
+
name: 'makerAddress',
|
|
1774
|
+
type: 'address'
|
|
1775
|
+
}, {
|
|
1776
|
+
internalType: 'address',
|
|
1777
|
+
name: 'takerAddress',
|
|
1778
|
+
type: 'address'
|
|
1779
|
+
}, {
|
|
1780
|
+
internalType: 'address',
|
|
1781
|
+
name: 'feeRecipientAddress',
|
|
1782
|
+
type: 'address'
|
|
1783
|
+
}, {
|
|
1784
|
+
internalType: 'address',
|
|
1785
|
+
name: 'senderAddress',
|
|
1786
|
+
type: 'address'
|
|
1787
|
+
}, {
|
|
1788
|
+
internalType: 'uint256',
|
|
1789
|
+
name: 'makerAssetAmount',
|
|
1790
|
+
type: 'uint256'
|
|
1791
|
+
}, {
|
|
1792
|
+
internalType: 'uint256',
|
|
1793
|
+
name: 'takerAssetAmount',
|
|
1794
|
+
type: 'uint256'
|
|
1795
|
+
}, {
|
|
1796
|
+
internalType: 'uint256',
|
|
1797
|
+
name: 'makerFee',
|
|
1798
|
+
type: 'uint256'
|
|
1799
|
+
}, {
|
|
1800
|
+
internalType: 'uint256',
|
|
1801
|
+
name: 'takerFee',
|
|
1802
|
+
type: 'uint256'
|
|
1803
|
+
}, {
|
|
1804
|
+
internalType: 'uint256',
|
|
1805
|
+
name: 'expirationTimeSeconds',
|
|
1806
|
+
type: 'uint256'
|
|
1807
|
+
}, {
|
|
1808
|
+
internalType: 'uint256',
|
|
1809
|
+
name: 'salt',
|
|
1810
|
+
type: 'uint256'
|
|
1811
|
+
}, {
|
|
1812
|
+
internalType: 'bytes',
|
|
1813
|
+
name: 'makerAssetData',
|
|
1814
|
+
type: 'bytes'
|
|
1815
|
+
}, {
|
|
1816
|
+
internalType: 'bytes',
|
|
1817
|
+
name: 'takerAssetData',
|
|
1818
|
+
type: 'bytes'
|
|
1819
|
+
}, {
|
|
1820
|
+
internalType: 'bytes',
|
|
1821
|
+
name: 'makerFeeAssetData',
|
|
1822
|
+
type: 'bytes'
|
|
1823
|
+
}, {
|
|
1824
|
+
internalType: 'bytes',
|
|
1825
|
+
name: 'takerFeeAssetData',
|
|
1826
|
+
type: 'bytes'
|
|
1827
|
+
}],
|
|
1828
|
+
internalType: 'struct IEIP1271Data.Order',
|
|
1829
|
+
name: 'order',
|
|
1830
|
+
type: 'tuple'
|
|
1831
|
+
}, {
|
|
1832
|
+
internalType: 'bytes32',
|
|
1833
|
+
name: 'orderHash',
|
|
1834
|
+
type: 'bytes32'
|
|
1835
|
+
}],
|
|
1836
|
+
name: 'OrderWithHash',
|
|
1837
|
+
outputs: [],
|
|
1838
|
+
stateMutability: 'pure',
|
|
1839
|
+
type: 'function'
|
|
1840
|
+
}];
|
|
1841
|
+
|
|
1722
1842
|
const eip191prefix = ethers.ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
|
|
1723
1843
|
const messageToBytes = message => {
|
|
1724
1844
|
if (ethers.ethers.utils.isBytes(message) || ethers.ethers.utils.isHexString(message)) {
|
|
@@ -1729,7 +1849,12 @@ const messageToBytes = message => {
|
|
|
1729
1849
|
};
|
|
1730
1850
|
const prefixEIP191Message = message => {
|
|
1731
1851
|
const messageBytes = messageToBytes(message);
|
|
1732
|
-
|
|
1852
|
+
|
|
1853
|
+
if (messageIsExemptFromEIP191Prefix(messageBytes)) {
|
|
1854
|
+
return messageBytes;
|
|
1855
|
+
} else {
|
|
1856
|
+
return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
|
|
1857
|
+
}
|
|
1733
1858
|
};
|
|
1734
1859
|
const isValidSignature = async (address, digest, sig, provider, chainId, walletContext) => {
|
|
1735
1860
|
if (!chainId) {
|
|
@@ -479,12 +479,13 @@ class WalletRequestHandler {
|
|
|
479
479
|
// signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
|
|
480
480
|
// value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
|
|
481
481
|
// a Signer value is the actually interface to a signed-in account
|
|
482
|
-
constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
|
|
482
|
+
constructor(_signer, prompter, auxDataProvider, mainnetNetworks, testnetNetworks = []) {
|
|
483
483
|
var _this = this;
|
|
484
484
|
|
|
485
485
|
this.signer = void 0;
|
|
486
486
|
this.signerReadyCallbacks = [];
|
|
487
487
|
this.prompter = void 0;
|
|
488
|
+
this.auxDataProvider = void 0;
|
|
488
489
|
this.mainnetNetworks = void 0;
|
|
489
490
|
this.testnetNetworks = void 0;
|
|
490
491
|
this._openIntent = void 0;
|
|
@@ -958,6 +959,7 @@ class WalletRequestHandler {
|
|
|
958
959
|
|
|
959
960
|
this.signer = _signer;
|
|
960
961
|
this.prompter = prompter;
|
|
962
|
+
this.auxDataProvider = auxDataProvider;
|
|
961
963
|
this.mainnetNetworks = mainnetNetworks;
|
|
962
964
|
this.testnetNetworks = testnetNetworks;
|
|
963
965
|
}
|
|
@@ -1051,6 +1053,16 @@ class WalletRequestHandler {
|
|
|
1051
1053
|
chainId: ethers.utils.hexlify(await this.getChainId())
|
|
1052
1054
|
};
|
|
1053
1055
|
|
|
1056
|
+
if (options && options.askForEmail) {
|
|
1057
|
+
var _this$auxDataProvider;
|
|
1058
|
+
|
|
1059
|
+
const email = await ((_this$auxDataProvider = this.auxDataProvider) == null ? void 0 : _this$auxDataProvider.get('email'));
|
|
1060
|
+
|
|
1061
|
+
if (email) {
|
|
1062
|
+
connectDetails.email = email;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1054
1066
|
if (options && options.authorize) {
|
|
1055
1067
|
// Perform ethauth eip712 request and construct the ConnectDetails response
|
|
1056
1068
|
// including the auth proof
|
|
@@ -1335,7 +1347,7 @@ function isSequenceProvider(provider) {
|
|
|
1335
1347
|
}
|
|
1336
1348
|
class LocalWeb3Provider extends Web3Provider {
|
|
1337
1349
|
constructor(signer, networks) {
|
|
1338
|
-
const walletRequestHandler = new WalletRequestHandler(signer, null, networks || []);
|
|
1350
|
+
const walletRequestHandler = new WalletRequestHandler(signer, null, null, networks || []);
|
|
1339
1351
|
super(walletRequestHandler);
|
|
1340
1352
|
}
|
|
1341
1353
|
|
|
@@ -1715,6 +1727,114 @@ const hexlifyTransaction = (transaction, allowExtra) => {
|
|
|
1715
1727
|
return result;
|
|
1716
1728
|
};
|
|
1717
1729
|
|
|
1730
|
+
function messageIsExemptFromEIP191Prefix(message) {
|
|
1731
|
+
return EIP_191_PREFIX_EXCEPTIONS.some(e => e.predicate(message));
|
|
1732
|
+
}
|
|
1733
|
+
const EIP_191_PREFIX_EXCEPTIONS = [// NOTE: Decentraland does not support 191 correctly.
|
|
1734
|
+
{
|
|
1735
|
+
name: 'Decentraland Exception',
|
|
1736
|
+
predicate: isDecentralandLoginMessage
|
|
1737
|
+
}, // NOTE: 0x v3 does not support 191 correctly.
|
|
1738
|
+
// See https://gov.0x.org/t/zeip-proposal-fix-v3-eip-191-non-compliance-when-validating-eip-1271-signatures/3396 for more info.
|
|
1739
|
+
{
|
|
1740
|
+
name: '0x v3 Exception',
|
|
1741
|
+
predicate: isZeroExV3Order
|
|
1742
|
+
}];
|
|
1743
|
+
const DCL_REGEX = /^Decentraland Login\nEphemeral address: 0x[a-fA-F0-9]{40}\nExpiration: (\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)((-(\d{2}):(\d{2})|Z)?)$/;
|
|
1744
|
+
function isDecentralandLoginMessage(bytes) {
|
|
1745
|
+
try {
|
|
1746
|
+
const stringified = ethers.utils.toUtf8String(bytes);
|
|
1747
|
+
return DCL_REGEX.test(stringified);
|
|
1748
|
+
} catch (_unused) {
|
|
1749
|
+
return false;
|
|
1750
|
+
}
|
|
1751
|
+
} // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
|
|
1752
|
+
// see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
|
|
1753
|
+
|
|
1754
|
+
function isZeroExV3Order(bytes) {
|
|
1755
|
+
const abi = new ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
|
|
1756
|
+
|
|
1757
|
+
try {
|
|
1758
|
+
abi.decodeFunctionData('OrderWithHash', bytes);
|
|
1759
|
+
return true;
|
|
1760
|
+
} catch (err) {
|
|
1761
|
+
// failed to decode ABI, so it's not a v3 order.
|
|
1762
|
+
return false;
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
const ZeroXV3EIP1271OrderWithHashAbi = [{
|
|
1766
|
+
inputs: [{
|
|
1767
|
+
components: [{
|
|
1768
|
+
internalType: 'address',
|
|
1769
|
+
name: 'makerAddress',
|
|
1770
|
+
type: 'address'
|
|
1771
|
+
}, {
|
|
1772
|
+
internalType: 'address',
|
|
1773
|
+
name: 'takerAddress',
|
|
1774
|
+
type: 'address'
|
|
1775
|
+
}, {
|
|
1776
|
+
internalType: 'address',
|
|
1777
|
+
name: 'feeRecipientAddress',
|
|
1778
|
+
type: 'address'
|
|
1779
|
+
}, {
|
|
1780
|
+
internalType: 'address',
|
|
1781
|
+
name: 'senderAddress',
|
|
1782
|
+
type: 'address'
|
|
1783
|
+
}, {
|
|
1784
|
+
internalType: 'uint256',
|
|
1785
|
+
name: 'makerAssetAmount',
|
|
1786
|
+
type: 'uint256'
|
|
1787
|
+
}, {
|
|
1788
|
+
internalType: 'uint256',
|
|
1789
|
+
name: 'takerAssetAmount',
|
|
1790
|
+
type: 'uint256'
|
|
1791
|
+
}, {
|
|
1792
|
+
internalType: 'uint256',
|
|
1793
|
+
name: 'makerFee',
|
|
1794
|
+
type: 'uint256'
|
|
1795
|
+
}, {
|
|
1796
|
+
internalType: 'uint256',
|
|
1797
|
+
name: 'takerFee',
|
|
1798
|
+
type: 'uint256'
|
|
1799
|
+
}, {
|
|
1800
|
+
internalType: 'uint256',
|
|
1801
|
+
name: 'expirationTimeSeconds',
|
|
1802
|
+
type: 'uint256'
|
|
1803
|
+
}, {
|
|
1804
|
+
internalType: 'uint256',
|
|
1805
|
+
name: 'salt',
|
|
1806
|
+
type: 'uint256'
|
|
1807
|
+
}, {
|
|
1808
|
+
internalType: 'bytes',
|
|
1809
|
+
name: 'makerAssetData',
|
|
1810
|
+
type: 'bytes'
|
|
1811
|
+
}, {
|
|
1812
|
+
internalType: 'bytes',
|
|
1813
|
+
name: 'takerAssetData',
|
|
1814
|
+
type: 'bytes'
|
|
1815
|
+
}, {
|
|
1816
|
+
internalType: 'bytes',
|
|
1817
|
+
name: 'makerFeeAssetData',
|
|
1818
|
+
type: 'bytes'
|
|
1819
|
+
}, {
|
|
1820
|
+
internalType: 'bytes',
|
|
1821
|
+
name: 'takerFeeAssetData',
|
|
1822
|
+
type: 'bytes'
|
|
1823
|
+
}],
|
|
1824
|
+
internalType: 'struct IEIP1271Data.Order',
|
|
1825
|
+
name: 'order',
|
|
1826
|
+
type: 'tuple'
|
|
1827
|
+
}, {
|
|
1828
|
+
internalType: 'bytes32',
|
|
1829
|
+
name: 'orderHash',
|
|
1830
|
+
type: 'bytes32'
|
|
1831
|
+
}],
|
|
1832
|
+
name: 'OrderWithHash',
|
|
1833
|
+
outputs: [],
|
|
1834
|
+
stateMutability: 'pure',
|
|
1835
|
+
type: 'function'
|
|
1836
|
+
}];
|
|
1837
|
+
|
|
1718
1838
|
const eip191prefix = ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
|
|
1719
1839
|
const messageToBytes = message => {
|
|
1720
1840
|
if (ethers.utils.isBytes(message) || ethers.utils.isHexString(message)) {
|
|
@@ -1725,7 +1845,12 @@ const messageToBytes = message => {
|
|
|
1725
1845
|
};
|
|
1726
1846
|
const prefixEIP191Message = message => {
|
|
1727
1847
|
const messageBytes = messageToBytes(message);
|
|
1728
|
-
|
|
1848
|
+
|
|
1849
|
+
if (messageIsExemptFromEIP191Prefix(messageBytes)) {
|
|
1850
|
+
return messageBytes;
|
|
1851
|
+
} else {
|
|
1852
|
+
return ethers.utils.concat([eip191prefix, ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
|
|
1853
|
+
}
|
|
1729
1854
|
};
|
|
1730
1855
|
const isValidSignature = async (address, digest, sig, provider, chainId, walletContext) => {
|
|
1731
1856
|
if (!chainId) {
|
|
@@ -13,6 +13,7 @@ export declare class WalletRequestHandler implements ExternalProvider, JsonRpcHa
|
|
|
13
13
|
private signer;
|
|
14
14
|
private signerReadyCallbacks;
|
|
15
15
|
private prompter;
|
|
16
|
+
private auxDataProvider;
|
|
16
17
|
private mainnetNetworks;
|
|
17
18
|
private testnetNetworks;
|
|
18
19
|
private _openIntent?;
|
|
@@ -20,7 +21,7 @@ export declare class WalletRequestHandler implements ExternalProvider, JsonRpcHa
|
|
|
20
21
|
private _defaultNetworkId?;
|
|
21
22
|
private _chainId?;
|
|
22
23
|
private events;
|
|
23
|
-
constructor(signer: Signer | null | undefined, prompter: WalletUserPrompter | null, mainnetNetworks: NetworkConfig[], testnetNetworks?: NetworkConfig[]);
|
|
24
|
+
constructor(signer: Signer | null | undefined, prompter: WalletUserPrompter | null, auxDataProvider: AuxDataProvider | null, mainnetNetworks: NetworkConfig[], testnetNetworks?: NetworkConfig[]);
|
|
24
25
|
signIn(signer: Signer | null, options?: WalletSignInOptions): Promise<void>;
|
|
25
26
|
signOut(): void;
|
|
26
27
|
signerReset(): void;
|
|
@@ -58,3 +59,6 @@ export interface WalletUserPrompter {
|
|
|
58
59
|
promptSendTransaction(txn: TransactionRequest, chaindId?: number, options?: ConnectOptions): Promise<string>;
|
|
59
60
|
promptConfirmWalletDeploy(chainId: number, options?: ConnectOptions): Promise<boolean>;
|
|
60
61
|
}
|
|
62
|
+
export interface AuxDataProvider {
|
|
63
|
+
get(key: string): Promise<any>;
|
|
64
|
+
}
|
|
@@ -121,7 +121,7 @@ export interface ConnectOptions {
|
|
|
121
121
|
expiry?: number;
|
|
122
122
|
/** authorize will perform an ETHAuth eip712 signing and return the proof to the dapp. */
|
|
123
123
|
authorize?: boolean;
|
|
124
|
-
/**
|
|
124
|
+
/** askForEmail will prompt to give permission to the dapp to access email address */
|
|
125
125
|
askForEmail?: boolean;
|
|
126
126
|
/** refresh flag will force a full re-connect (ie. disconnect then connect again) */
|
|
127
127
|
refresh?: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xsequence/provider",
|
|
3
|
-
"version": "0.42.
|
|
3
|
+
"version": "0.42.10",
|
|
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",
|
|
@@ -9,17 +9,18 @@
|
|
|
9
9
|
"author": "Horizon Blockchain Games",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"scripts": {
|
|
12
|
-
"test": "
|
|
12
|
+
"test": "yarn test:file tests/**/*.spec.ts",
|
|
13
|
+
"test:file": "TS_NODE_PROJECT=../../tsconfig.test.json mocha -r ts-node/register --timeout 30000",
|
|
13
14
|
"typecheck": "tsc --noEmit"
|
|
14
15
|
},
|
|
15
16
|
"dependencies": {
|
|
16
|
-
"@0xsequence/abi": "^0.42.
|
|
17
|
-
"@0xsequence/auth": "^0.42.
|
|
18
|
-
"@0xsequence/config": "^0.42.
|
|
19
|
-
"@0xsequence/network": "^0.42.
|
|
20
|
-
"@0xsequence/transactions": "^0.42.
|
|
21
|
-
"@0xsequence/utils": "^0.42.
|
|
22
|
-
"@0xsequence/wallet": "^0.42.
|
|
17
|
+
"@0xsequence/abi": "^0.42.10",
|
|
18
|
+
"@0xsequence/auth": "^0.42.10",
|
|
19
|
+
"@0xsequence/config": "^0.42.10",
|
|
20
|
+
"@0xsequence/network": "^0.42.10",
|
|
21
|
+
"@0xsequence/transactions": "^0.42.10",
|
|
22
|
+
"@0xsequence/utils": "^0.42.10",
|
|
23
|
+
"@0xsequence/wallet": "^0.42.10",
|
|
23
24
|
"@ethersproject/abstract-signer": "^5.5.0",
|
|
24
25
|
"@ethersproject/hash": "^5.5.0",
|
|
25
26
|
"@ethersproject/providers": "^5.5.1",
|
|
@@ -34,4 +35,4 @@
|
|
|
34
35
|
"src",
|
|
35
36
|
"dist"
|
|
36
37
|
]
|
|
37
|
-
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { ethers } from 'ethers'
|
|
2
|
+
|
|
3
|
+
export function messageIsExemptFromEIP191Prefix(message: Uint8Array): boolean {
|
|
4
|
+
return EIP_191_PREFIX_EXCEPTIONS.some(e => e.predicate(message))
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const EIP_191_PREFIX_EXCEPTIONS: Array<{
|
|
8
|
+
name: string
|
|
9
|
+
predicate: (message: Uint8Array) => boolean
|
|
10
|
+
}> = [
|
|
11
|
+
// NOTE: Decentraland does not support 191 correctly.
|
|
12
|
+
{
|
|
13
|
+
name: 'Decentraland Exception',
|
|
14
|
+
predicate: isDecentralandLoginMessage
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
// NOTE: 0x v3 does not support 191 correctly.
|
|
18
|
+
// See https://gov.0x.org/t/zeip-proposal-fix-v3-eip-191-non-compliance-when-validating-eip-1271-signatures/3396 for more info.
|
|
19
|
+
{ name: '0x v3 Exception', predicate: isZeroExV3Order }
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
const DCL_REGEX =
|
|
23
|
+
/^Decentraland Login\nEphemeral address: 0x[a-fA-F0-9]{40}\nExpiration: (\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)((-(\d{2}):(\d{2})|Z)?)$/
|
|
24
|
+
export function isDecentralandLoginMessage(bytes: Uint8Array): boolean {
|
|
25
|
+
try {
|
|
26
|
+
const stringified = ethers.utils.toUtf8String(bytes)
|
|
27
|
+
return DCL_REGEX.test(stringified)
|
|
28
|
+
} catch {
|
|
29
|
+
return false
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
|
|
34
|
+
// see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
|
|
35
|
+
export function isZeroExV3Order(bytes: Uint8Array): boolean {
|
|
36
|
+
const abi = new ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi)
|
|
37
|
+
try {
|
|
38
|
+
abi.decodeFunctionData('OrderWithHash', bytes)
|
|
39
|
+
return true
|
|
40
|
+
} catch (err) {
|
|
41
|
+
// failed to decode ABI, so it's not a v3 order.
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const ZeroXV3EIP1271OrderWithHashAbi = [
|
|
47
|
+
{
|
|
48
|
+
inputs: [
|
|
49
|
+
{
|
|
50
|
+
components: [
|
|
51
|
+
{
|
|
52
|
+
internalType: 'address',
|
|
53
|
+
name: 'makerAddress',
|
|
54
|
+
type: 'address'
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
internalType: 'address',
|
|
58
|
+
name: 'takerAddress',
|
|
59
|
+
type: 'address'
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
internalType: 'address',
|
|
63
|
+
name: 'feeRecipientAddress',
|
|
64
|
+
type: 'address'
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
internalType: 'address',
|
|
68
|
+
name: 'senderAddress',
|
|
69
|
+
type: 'address'
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
internalType: 'uint256',
|
|
73
|
+
name: 'makerAssetAmount',
|
|
74
|
+
type: 'uint256'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
internalType: 'uint256',
|
|
78
|
+
name: 'takerAssetAmount',
|
|
79
|
+
type: 'uint256'
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
internalType: 'uint256',
|
|
83
|
+
name: 'makerFee',
|
|
84
|
+
type: 'uint256'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
internalType: 'uint256',
|
|
88
|
+
name: 'takerFee',
|
|
89
|
+
type: 'uint256'
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
internalType: 'uint256',
|
|
93
|
+
name: 'expirationTimeSeconds',
|
|
94
|
+
type: 'uint256'
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
internalType: 'uint256',
|
|
98
|
+
name: 'salt',
|
|
99
|
+
type: 'uint256'
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
internalType: 'bytes',
|
|
103
|
+
name: 'makerAssetData',
|
|
104
|
+
type: 'bytes'
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
internalType: 'bytes',
|
|
108
|
+
name: 'takerAssetData',
|
|
109
|
+
type: 'bytes'
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
internalType: 'bytes',
|
|
113
|
+
name: 'makerFeeAssetData',
|
|
114
|
+
type: 'bytes'
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
internalType: 'bytes',
|
|
118
|
+
name: 'takerFeeAssetData',
|
|
119
|
+
type: 'bytes'
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
internalType: 'struct IEIP1271Data.Order',
|
|
123
|
+
name: 'order',
|
|
124
|
+
type: 'tuple'
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
internalType: 'bytes32',
|
|
128
|
+
name: 'orderHash',
|
|
129
|
+
type: 'bytes32'
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
name: 'OrderWithHash',
|
|
133
|
+
outputs: [],
|
|
134
|
+
stateMutability: 'pure',
|
|
135
|
+
type: 'function'
|
|
136
|
+
}
|
|
137
|
+
]
|
package/src/provider.ts
CHANGED
|
@@ -94,7 +94,7 @@ export function isSequenceProvider(provider: any): provider is Web3Provider {
|
|
|
94
94
|
|
|
95
95
|
export class LocalWeb3Provider extends Web3Provider {
|
|
96
96
|
constructor(signer: Signer, networks?: NetworkConfig[]) {
|
|
97
|
-
const walletRequestHandler = new WalletRequestHandler(signer, null, networks || [])
|
|
97
|
+
const walletRequestHandler = new WalletRequestHandler(signer, null, null, networks || [])
|
|
98
98
|
super(walletRequestHandler)
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -44,6 +44,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
|
|
|
44
44
|
private signerReadyCallbacks: Array<() => void> = []
|
|
45
45
|
|
|
46
46
|
private prompter: WalletUserPrompter | null
|
|
47
|
+
private auxDataProvider: AuxDataProvider | null
|
|
47
48
|
private mainnetNetworks: NetworkConfig[]
|
|
48
49
|
private testnetNetworks: NetworkConfig[]
|
|
49
50
|
|
|
@@ -57,11 +58,13 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
|
|
|
57
58
|
constructor(
|
|
58
59
|
signer: Signer | null | undefined,
|
|
59
60
|
prompter: WalletUserPrompter | null,
|
|
61
|
+
auxDataProvider: AuxDataProvider | null,
|
|
60
62
|
mainnetNetworks: NetworkConfig[],
|
|
61
63
|
testnetNetworks: NetworkConfig[] = []
|
|
62
64
|
) {
|
|
63
65
|
this.signer = signer
|
|
64
66
|
this.prompter = prompter
|
|
67
|
+
this.auxDataProvider = auxDataProvider
|
|
65
68
|
this.mainnetNetworks = mainnetNetworks
|
|
66
69
|
this.testnetNetworks = testnetNetworks
|
|
67
70
|
}
|
|
@@ -152,6 +155,13 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
|
|
|
152
155
|
chainId: ethers.utils.hexlify(await this.getChainId())
|
|
153
156
|
}
|
|
154
157
|
|
|
158
|
+
if (options && options.askForEmail) {
|
|
159
|
+
const email = await this.auxDataProvider?.get('email')
|
|
160
|
+
if (email) {
|
|
161
|
+
connectDetails.email = email
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
155
165
|
if (options && options.authorize) {
|
|
156
166
|
// Perform ethauth eip712 request and construct the ConnectDetails response
|
|
157
167
|
// including the auth proof
|
|
@@ -802,6 +812,10 @@ export interface WalletUserPrompter {
|
|
|
802
812
|
promptConfirmWalletDeploy(chainId: number, options?: ConnectOptions): Promise<boolean>
|
|
803
813
|
}
|
|
804
814
|
|
|
815
|
+
export interface AuxDataProvider {
|
|
816
|
+
get(key: string): Promise<any>
|
|
817
|
+
}
|
|
818
|
+
|
|
805
819
|
const permittedJsonRpcMethods = [
|
|
806
820
|
'net_version',
|
|
807
821
|
'eth_chainId',
|
package/src/types.ts
CHANGED
|
@@ -156,8 +156,7 @@ export interface ConnectOptions {
|
|
|
156
156
|
/** authorize will perform an ETHAuth eip712 signing and return the proof to the dapp. */
|
|
157
157
|
authorize?: boolean
|
|
158
158
|
|
|
159
|
-
/**
|
|
160
|
-
// TODO: this feature is currently not used as the wallet does not report emails yet
|
|
159
|
+
/** askForEmail will prompt to give permission to the dapp to access email address */
|
|
161
160
|
askForEmail?: boolean
|
|
162
161
|
|
|
163
162
|
/** refresh flag will force a full re-connect (ie. disconnect then connect again) */
|
package/src/utils/index.ts
CHANGED
|
@@ -113,7 +113,13 @@ export class WalletUtils {
|
|
|
113
113
|
walletContext?: WalletContext
|
|
114
114
|
): Promise<WalletConfig> => {
|
|
115
115
|
walletContext = walletContext || (await this.wallet.getWalletContext())
|
|
116
|
-
return recoverWalletConfig(
|
|
116
|
+
return recoverWalletConfig(
|
|
117
|
+
address,
|
|
118
|
+
encodeMessageDigest(prefixEIP191Message(message)),
|
|
119
|
+
signature,
|
|
120
|
+
chainId,
|
|
121
|
+
walletContext
|
|
122
|
+
)
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
// Recover the WalletConfig from a signature of a typedData object
|
package/src/utils.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { WalletConfig, addressOf, DecodedSignature, isConfigEqual } from '@0xseq
|
|
|
4
4
|
import { packMessageData, encodeMessageDigest, TypedData, encodeTypedDataDigest } from '@0xsequence/utils'
|
|
5
5
|
import { Web3Provider } from './provider'
|
|
6
6
|
import { isValidSignature as _isValidSignature, recoverConfig, Signer } from '@0xsequence/wallet'
|
|
7
|
+
import { messageIsExemptFromEIP191Prefix } from './eip191exceptions'
|
|
7
8
|
|
|
8
9
|
const eip191prefix = ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n')
|
|
9
10
|
|
|
@@ -17,7 +18,11 @@ export const messageToBytes = (message: BytesLike): Uint8Array => {
|
|
|
17
18
|
|
|
18
19
|
export const prefixEIP191Message = (message: BytesLike): Uint8Array => {
|
|
19
20
|
const messageBytes = messageToBytes(message)
|
|
20
|
-
|
|
21
|
+
if (messageIsExemptFromEIP191Prefix(messageBytes)) {
|
|
22
|
+
return messageBytes
|
|
23
|
+
} else {
|
|
24
|
+
return ethers.utils.concat([eip191prefix, ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes])
|
|
25
|
+
}
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
export const isValidSignature = async (
|