@0xsequence/provider 0.42.7 → 0.42.9

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.
@@ -1719,6 +1719,114 @@ const hexlifyTransaction = (transaction, allowExtra) => {
1719
1719
  return result;
1720
1720
  };
1721
1721
 
1722
+ function messageIsExemptFromEIP191Prefix(message) {
1723
+ return EIP_191_PREFIX_EXCEPTIONS.some(e => e.predicate(message));
1724
+ }
1725
+ const EIP_191_PREFIX_EXCEPTIONS = [// NOTE: Decentraland does not support 191 correctly.
1726
+ {
1727
+ name: 'Decentraland Exception',
1728
+ predicate: isDecentralandLoginMessage
1729
+ }, // NOTE: 0x v3 does not support 191 correctly.
1730
+ // See https://gov.0x.org/t/zeip-proposal-fix-v3-eip-191-non-compliance-when-validating-eip-1271-signatures/3396 for more info.
1731
+ {
1732
+ name: '0x v3 Exception',
1733
+ predicate: isZeroExV3Order
1734
+ }];
1735
+ 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)?)$/;
1736
+ function isDecentralandLoginMessage(bytes) {
1737
+ try {
1738
+ const stringified = ethers.ethers.utils.toUtf8String(bytes);
1739
+ return DCL_REGEX.test(stringified);
1740
+ } catch (_unused) {
1741
+ return false;
1742
+ }
1743
+ } // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
1744
+ // see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
1745
+
1746
+ function isZeroExV3Order(bytes) {
1747
+ const abi = new ethers.ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
1748
+
1749
+ try {
1750
+ abi.decodeFunctionData('OrderWithHash', bytes);
1751
+ return true;
1752
+ } catch (err) {
1753
+ // failed to decode ABI, so it's not a v3 order.
1754
+ return false;
1755
+ }
1756
+ }
1757
+ const ZeroXV3EIP1271OrderWithHashAbi = [{
1758
+ inputs: [{
1759
+ components: [{
1760
+ internalType: 'address',
1761
+ name: 'makerAddress',
1762
+ type: 'address'
1763
+ }, {
1764
+ internalType: 'address',
1765
+ name: 'takerAddress',
1766
+ type: 'address'
1767
+ }, {
1768
+ internalType: 'address',
1769
+ name: 'feeRecipientAddress',
1770
+ type: 'address'
1771
+ }, {
1772
+ internalType: 'address',
1773
+ name: 'senderAddress',
1774
+ type: 'address'
1775
+ }, {
1776
+ internalType: 'uint256',
1777
+ name: 'makerAssetAmount',
1778
+ type: 'uint256'
1779
+ }, {
1780
+ internalType: 'uint256',
1781
+ name: 'takerAssetAmount',
1782
+ type: 'uint256'
1783
+ }, {
1784
+ internalType: 'uint256',
1785
+ name: 'makerFee',
1786
+ type: 'uint256'
1787
+ }, {
1788
+ internalType: 'uint256',
1789
+ name: 'takerFee',
1790
+ type: 'uint256'
1791
+ }, {
1792
+ internalType: 'uint256',
1793
+ name: 'expirationTimeSeconds',
1794
+ type: 'uint256'
1795
+ }, {
1796
+ internalType: 'uint256',
1797
+ name: 'salt',
1798
+ type: 'uint256'
1799
+ }, {
1800
+ internalType: 'bytes',
1801
+ name: 'makerAssetData',
1802
+ type: 'bytes'
1803
+ }, {
1804
+ internalType: 'bytes',
1805
+ name: 'takerAssetData',
1806
+ type: 'bytes'
1807
+ }, {
1808
+ internalType: 'bytes',
1809
+ name: 'makerFeeAssetData',
1810
+ type: 'bytes'
1811
+ }, {
1812
+ internalType: 'bytes',
1813
+ name: 'takerFeeAssetData',
1814
+ type: 'bytes'
1815
+ }],
1816
+ internalType: 'struct IEIP1271Data.Order',
1817
+ name: 'order',
1818
+ type: 'tuple'
1819
+ }, {
1820
+ internalType: 'bytes32',
1821
+ name: 'orderHash',
1822
+ type: 'bytes32'
1823
+ }],
1824
+ name: 'OrderWithHash',
1825
+ outputs: [],
1826
+ stateMutability: 'pure',
1827
+ type: 'function'
1828
+ }];
1829
+
1722
1830
  const eip191prefix = ethers.ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
1723
1831
  const messageToBytes = message => {
1724
1832
  if (ethers.ethers.utils.isBytes(message) || ethers.ethers.utils.isHexString(message)) {
@@ -1729,7 +1837,12 @@ const messageToBytes = message => {
1729
1837
  };
1730
1838
  const prefixEIP191Message = message => {
1731
1839
  const messageBytes = messageToBytes(message);
1732
- return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
1840
+
1841
+ if (messageIsExemptFromEIP191Prefix(messageBytes)) {
1842
+ return messageBytes;
1843
+ } else {
1844
+ return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
1845
+ }
1733
1846
  };
1734
1847
  const isValidSignature = async (address, digest, sig, provider, chainId, walletContext) => {
1735
1848
  if (!chainId) {
@@ -1769,6 +1882,7 @@ const recoverWalletConfig = async (address, digest, signature, chainId, walletCo
1769
1882
  return config$1;
1770
1883
  };
1771
1884
  const isBrowserExtension = () => window.location.protocol === 'chrome-extension:' || window.location.protocol === 'moz-extension:';
1885
+ const isUnityPlugin = () => !!navigator.userAgent.match(/UnitySequence/i);
1772
1886
  /**
1773
1887
  * Returns the status of a signer's wallet on given chain by checking wallet deployment and config status
1774
1888
  *
@@ -2746,7 +2860,7 @@ class WindowMessageProvider extends BaseProviderTransport {
2746
2860
  if (!intent.options) intent.options = {}; // skip setting origin host if we're in an browser extension execution context
2747
2861
  // allow origin that is passed in
2748
2862
 
2749
- if (!isBrowserExtension()) {
2863
+ if (!isBrowserExtension() && !isUnityPlugin()) {
2750
2864
  intent.options.origin = window.location.origin;
2751
2865
  }
2752
2866
  } // encode intent as base64 url-encoded param
@@ -4116,6 +4230,7 @@ exports.getWallet = getWallet;
4116
4230
  exports.initWallet = initWallet;
4117
4231
  exports.isBrowserExtension = isBrowserExtension;
4118
4232
  exports.isSequenceProvider = isSequenceProvider;
4233
+ exports.isUnityPlugin = isUnityPlugin;
4119
4234
  exports.isValidMessageSignature = isValidMessageSignature;
4120
4235
  exports.isValidSignature = isValidSignature;
4121
4236
  exports.isValidTypedDataSignature = isValidTypedDataSignature;
@@ -1719,6 +1719,114 @@ const hexlifyTransaction = (transaction, allowExtra) => {
1719
1719
  return result;
1720
1720
  };
1721
1721
 
1722
+ function messageIsExemptFromEIP191Prefix(message) {
1723
+ return EIP_191_PREFIX_EXCEPTIONS.some(e => e.predicate(message));
1724
+ }
1725
+ const EIP_191_PREFIX_EXCEPTIONS = [// NOTE: Decentraland does not support 191 correctly.
1726
+ {
1727
+ name: 'Decentraland Exception',
1728
+ predicate: isDecentralandLoginMessage
1729
+ }, // NOTE: 0x v3 does not support 191 correctly.
1730
+ // See https://gov.0x.org/t/zeip-proposal-fix-v3-eip-191-non-compliance-when-validating-eip-1271-signatures/3396 for more info.
1731
+ {
1732
+ name: '0x v3 Exception',
1733
+ predicate: isZeroExV3Order
1734
+ }];
1735
+ 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)?)$/;
1736
+ function isDecentralandLoginMessage(bytes) {
1737
+ try {
1738
+ const stringified = ethers.ethers.utils.toUtf8String(bytes);
1739
+ return DCL_REGEX.test(stringified);
1740
+ } catch (_unused) {
1741
+ return false;
1742
+ }
1743
+ } // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
1744
+ // see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
1745
+
1746
+ function isZeroExV3Order(bytes) {
1747
+ const abi = new ethers.ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
1748
+
1749
+ try {
1750
+ abi.decodeFunctionData('OrderWithHash', bytes);
1751
+ return true;
1752
+ } catch (err) {
1753
+ // failed to decode ABI, so it's not a v3 order.
1754
+ return false;
1755
+ }
1756
+ }
1757
+ const ZeroXV3EIP1271OrderWithHashAbi = [{
1758
+ inputs: [{
1759
+ components: [{
1760
+ internalType: 'address',
1761
+ name: 'makerAddress',
1762
+ type: 'address'
1763
+ }, {
1764
+ internalType: 'address',
1765
+ name: 'takerAddress',
1766
+ type: 'address'
1767
+ }, {
1768
+ internalType: 'address',
1769
+ name: 'feeRecipientAddress',
1770
+ type: 'address'
1771
+ }, {
1772
+ internalType: 'address',
1773
+ name: 'senderAddress',
1774
+ type: 'address'
1775
+ }, {
1776
+ internalType: 'uint256',
1777
+ name: 'makerAssetAmount',
1778
+ type: 'uint256'
1779
+ }, {
1780
+ internalType: 'uint256',
1781
+ name: 'takerAssetAmount',
1782
+ type: 'uint256'
1783
+ }, {
1784
+ internalType: 'uint256',
1785
+ name: 'makerFee',
1786
+ type: 'uint256'
1787
+ }, {
1788
+ internalType: 'uint256',
1789
+ name: 'takerFee',
1790
+ type: 'uint256'
1791
+ }, {
1792
+ internalType: 'uint256',
1793
+ name: 'expirationTimeSeconds',
1794
+ type: 'uint256'
1795
+ }, {
1796
+ internalType: 'uint256',
1797
+ name: 'salt',
1798
+ type: 'uint256'
1799
+ }, {
1800
+ internalType: 'bytes',
1801
+ name: 'makerAssetData',
1802
+ type: 'bytes'
1803
+ }, {
1804
+ internalType: 'bytes',
1805
+ name: 'takerAssetData',
1806
+ type: 'bytes'
1807
+ }, {
1808
+ internalType: 'bytes',
1809
+ name: 'makerFeeAssetData',
1810
+ type: 'bytes'
1811
+ }, {
1812
+ internalType: 'bytes',
1813
+ name: 'takerFeeAssetData',
1814
+ type: 'bytes'
1815
+ }],
1816
+ internalType: 'struct IEIP1271Data.Order',
1817
+ name: 'order',
1818
+ type: 'tuple'
1819
+ }, {
1820
+ internalType: 'bytes32',
1821
+ name: 'orderHash',
1822
+ type: 'bytes32'
1823
+ }],
1824
+ name: 'OrderWithHash',
1825
+ outputs: [],
1826
+ stateMutability: 'pure',
1827
+ type: 'function'
1828
+ }];
1829
+
1722
1830
  const eip191prefix = ethers.ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
1723
1831
  const messageToBytes = message => {
1724
1832
  if (ethers.ethers.utils.isBytes(message) || ethers.ethers.utils.isHexString(message)) {
@@ -1729,7 +1837,12 @@ const messageToBytes = message => {
1729
1837
  };
1730
1838
  const prefixEIP191Message = message => {
1731
1839
  const messageBytes = messageToBytes(message);
1732
- return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
1840
+
1841
+ if (messageIsExemptFromEIP191Prefix(messageBytes)) {
1842
+ return messageBytes;
1843
+ } else {
1844
+ return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
1845
+ }
1733
1846
  };
1734
1847
  const isValidSignature = async (address, digest, sig, provider, chainId, walletContext) => {
1735
1848
  if (!chainId) {
@@ -1769,6 +1882,7 @@ const recoverWalletConfig = async (address, digest, signature, chainId, walletCo
1769
1882
  return config$1;
1770
1883
  };
1771
1884
  const isBrowserExtension = () => window.location.protocol === 'chrome-extension:' || window.location.protocol === 'moz-extension:';
1885
+ const isUnityPlugin = () => !!navigator.userAgent.match(/UnitySequence/i);
1772
1886
  /**
1773
1887
  * Returns the status of a signer's wallet on given chain by checking wallet deployment and config status
1774
1888
  *
@@ -2746,7 +2860,7 @@ class WindowMessageProvider extends BaseProviderTransport {
2746
2860
  if (!intent.options) intent.options = {}; // skip setting origin host if we're in an browser extension execution context
2747
2861
  // allow origin that is passed in
2748
2862
 
2749
- if (!isBrowserExtension()) {
2863
+ if (!isBrowserExtension() && !isUnityPlugin()) {
2750
2864
  intent.options.origin = window.location.origin;
2751
2865
  }
2752
2866
  } // encode intent as base64 url-encoded param
@@ -4116,6 +4230,7 @@ exports.getWallet = getWallet;
4116
4230
  exports.initWallet = initWallet;
4117
4231
  exports.isBrowserExtension = isBrowserExtension;
4118
4232
  exports.isSequenceProvider = isSequenceProvider;
4233
+ exports.isUnityPlugin = isUnityPlugin;
4119
4234
  exports.isValidMessageSignature = isValidMessageSignature;
4120
4235
  exports.isValidSignature = isValidSignature;
4121
4236
  exports.isValidTypedDataSignature = isValidTypedDataSignature;
@@ -1715,6 +1715,114 @@ const hexlifyTransaction = (transaction, allowExtra) => {
1715
1715
  return result;
1716
1716
  };
1717
1717
 
1718
+ function messageIsExemptFromEIP191Prefix(message) {
1719
+ return EIP_191_PREFIX_EXCEPTIONS.some(e => e.predicate(message));
1720
+ }
1721
+ const EIP_191_PREFIX_EXCEPTIONS = [// NOTE: Decentraland does not support 191 correctly.
1722
+ {
1723
+ name: 'Decentraland Exception',
1724
+ predicate: isDecentralandLoginMessage
1725
+ }, // NOTE: 0x v3 does not support 191 correctly.
1726
+ // See https://gov.0x.org/t/zeip-proposal-fix-v3-eip-191-non-compliance-when-validating-eip-1271-signatures/3396 for more info.
1727
+ {
1728
+ name: '0x v3 Exception',
1729
+ predicate: isZeroExV3Order
1730
+ }];
1731
+ 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)?)$/;
1732
+ function isDecentralandLoginMessage(bytes) {
1733
+ try {
1734
+ const stringified = ethers.utils.toUtf8String(bytes);
1735
+ return DCL_REGEX.test(stringified);
1736
+ } catch (_unused) {
1737
+ return false;
1738
+ }
1739
+ } // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
1740
+ // see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
1741
+
1742
+ function isZeroExV3Order(bytes) {
1743
+ const abi = new ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
1744
+
1745
+ try {
1746
+ abi.decodeFunctionData('OrderWithHash', bytes);
1747
+ return true;
1748
+ } catch (err) {
1749
+ // failed to decode ABI, so it's not a v3 order.
1750
+ return false;
1751
+ }
1752
+ }
1753
+ const ZeroXV3EIP1271OrderWithHashAbi = [{
1754
+ inputs: [{
1755
+ components: [{
1756
+ internalType: 'address',
1757
+ name: 'makerAddress',
1758
+ type: 'address'
1759
+ }, {
1760
+ internalType: 'address',
1761
+ name: 'takerAddress',
1762
+ type: 'address'
1763
+ }, {
1764
+ internalType: 'address',
1765
+ name: 'feeRecipientAddress',
1766
+ type: 'address'
1767
+ }, {
1768
+ internalType: 'address',
1769
+ name: 'senderAddress',
1770
+ type: 'address'
1771
+ }, {
1772
+ internalType: 'uint256',
1773
+ name: 'makerAssetAmount',
1774
+ type: 'uint256'
1775
+ }, {
1776
+ internalType: 'uint256',
1777
+ name: 'takerAssetAmount',
1778
+ type: 'uint256'
1779
+ }, {
1780
+ internalType: 'uint256',
1781
+ name: 'makerFee',
1782
+ type: 'uint256'
1783
+ }, {
1784
+ internalType: 'uint256',
1785
+ name: 'takerFee',
1786
+ type: 'uint256'
1787
+ }, {
1788
+ internalType: 'uint256',
1789
+ name: 'expirationTimeSeconds',
1790
+ type: 'uint256'
1791
+ }, {
1792
+ internalType: 'uint256',
1793
+ name: 'salt',
1794
+ type: 'uint256'
1795
+ }, {
1796
+ internalType: 'bytes',
1797
+ name: 'makerAssetData',
1798
+ type: 'bytes'
1799
+ }, {
1800
+ internalType: 'bytes',
1801
+ name: 'takerAssetData',
1802
+ type: 'bytes'
1803
+ }, {
1804
+ internalType: 'bytes',
1805
+ name: 'makerFeeAssetData',
1806
+ type: 'bytes'
1807
+ }, {
1808
+ internalType: 'bytes',
1809
+ name: 'takerFeeAssetData',
1810
+ type: 'bytes'
1811
+ }],
1812
+ internalType: 'struct IEIP1271Data.Order',
1813
+ name: 'order',
1814
+ type: 'tuple'
1815
+ }, {
1816
+ internalType: 'bytes32',
1817
+ name: 'orderHash',
1818
+ type: 'bytes32'
1819
+ }],
1820
+ name: 'OrderWithHash',
1821
+ outputs: [],
1822
+ stateMutability: 'pure',
1823
+ type: 'function'
1824
+ }];
1825
+
1718
1826
  const eip191prefix = ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
1719
1827
  const messageToBytes = message => {
1720
1828
  if (ethers.utils.isBytes(message) || ethers.utils.isHexString(message)) {
@@ -1725,7 +1833,12 @@ const messageToBytes = message => {
1725
1833
  };
1726
1834
  const prefixEIP191Message = message => {
1727
1835
  const messageBytes = messageToBytes(message);
1728
- return ethers.utils.concat([eip191prefix, ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
1836
+
1837
+ if (messageIsExemptFromEIP191Prefix(messageBytes)) {
1838
+ return messageBytes;
1839
+ } else {
1840
+ return ethers.utils.concat([eip191prefix, ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
1841
+ }
1729
1842
  };
1730
1843
  const isValidSignature = async (address, digest, sig, provider, chainId, walletContext) => {
1731
1844
  if (!chainId) {
@@ -1765,6 +1878,7 @@ const recoverWalletConfig = async (address, digest, signature, chainId, walletCo
1765
1878
  return config;
1766
1879
  };
1767
1880
  const isBrowserExtension = () => window.location.protocol === 'chrome-extension:' || window.location.protocol === 'moz-extension:';
1881
+ const isUnityPlugin = () => !!navigator.userAgent.match(/UnitySequence/i);
1768
1882
  /**
1769
1883
  * Returns the status of a signer's wallet on given chain by checking wallet deployment and config status
1770
1884
  *
@@ -2742,7 +2856,7 @@ class WindowMessageProvider extends BaseProviderTransport {
2742
2856
  if (!intent.options) intent.options = {}; // skip setting origin host if we're in an browser extension execution context
2743
2857
  // allow origin that is passed in
2744
2858
 
2745
- if (!isBrowserExtension()) {
2859
+ if (!isBrowserExtension() && !isUnityPlugin()) {
2746
2860
  intent.options.origin = window.location.origin;
2747
2861
  }
2748
2862
  } // encode intent as base64 url-encoded param
@@ -4081,4 +4195,4 @@ const getWallet = () => {
4081
4195
  return walletInstance;
4082
4196
  };
4083
4197
 
4084
- export { BaseInjectedTransport, BaseProviderTransport, BaseWalletTransport, CHANNEL_ID, DefaultProviderConfig, ErrSignedInRequired, EventType, ExtensionMessageHandler, ExtensionMessageProvider, InitState, LocalStorage, LocalStore, LocalWeb3Provider, MuxMessageProvider, OpenState, PROVIDER_OPEN_TIMEOUT, ProviderError, ProxyMessageChannel, ProxyMessageChannelPort, ProxyMessageHandler, ProxyMessageProvider, UnrealMessageHandler, UnrealMessageProvider, Wallet, WalletRequestHandler, Web3Provider, Web3Signer, WindowMessageHandler, WindowMessageProvider, WindowSessionParams, getWallet, initWallet, isBrowserExtension, isSequenceProvider, isValidMessageSignature, isValidSignature, isValidTypedDataSignature, isWalletUpToDate, messageToBytes, nextMessageIdx, prefixEIP191Message, recoverWalletConfig };
4198
+ export { BaseInjectedTransport, BaseProviderTransport, BaseWalletTransport, CHANNEL_ID, DefaultProviderConfig, ErrSignedInRequired, EventType, ExtensionMessageHandler, ExtensionMessageProvider, InitState, LocalStorage, LocalStore, LocalWeb3Provider, MuxMessageProvider, OpenState, PROVIDER_OPEN_TIMEOUT, ProviderError, ProxyMessageChannel, ProxyMessageChannelPort, ProxyMessageHandler, ProxyMessageProvider, UnrealMessageHandler, UnrealMessageProvider, Wallet, WalletRequestHandler, Web3Provider, Web3Signer, WindowMessageHandler, WindowMessageProvider, WindowSessionParams, getWallet, initWallet, isBrowserExtension, isSequenceProvider, isUnityPlugin, isValidMessageSignature, isValidSignature, isValidTypedDataSignature, isWalletUpToDate, messageToBytes, nextMessageIdx, prefixEIP191Message, recoverWalletConfig };
@@ -0,0 +1,3 @@
1
+ export declare function messageIsExemptFromEIP191Prefix(message: Uint8Array): boolean;
2
+ export declare function isDecentralandLoginMessage(bytes: Uint8Array): boolean;
3
+ export declare function isZeroExV3Order(bytes: Uint8Array): boolean;
@@ -11,6 +11,7 @@ export declare const isValidMessageSignature: (address: string, message: string
11
11
  export declare const isValidTypedDataSignature: (address: string, typedData: TypedData, signature: string, provider: Web3Provider | ethers.providers.Web3Provider, chainId?: number | undefined, walletContext?: WalletContext | undefined) => Promise<boolean | undefined>;
12
12
  export declare const recoverWalletConfig: (address: string, digest: BytesLike, signature: string | DecodedSignature, chainId: BigNumberish, walletContext?: WalletContext | undefined) => Promise<WalletConfig>;
13
13
  export declare const isBrowserExtension: () => boolean;
14
+ export declare const isUnityPlugin: () => boolean;
14
15
  /**
15
16
  * Returns the status of a signer's wallet on given chain by checking wallet deployment and config status
16
17
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xsequence/provider",
3
- "version": "0.42.7",
3
+ "version": "0.42.9",
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": "echo",
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.7",
17
- "@0xsequence/auth": "^0.42.7",
18
- "@0xsequence/config": "^0.42.7",
19
- "@0xsequence/network": "^0.42.7",
20
- "@0xsequence/transactions": "^0.42.7",
21
- "@0xsequence/utils": "^0.42.7",
22
- "@0xsequence/wallet": "^0.42.7",
17
+ "@0xsequence/abi": "^0.42.9",
18
+ "@0xsequence/auth": "^0.42.9",
19
+ "@0xsequence/config": "^0.42.9",
20
+ "@0xsequence/network": "^0.42.9",
21
+ "@0xsequence/transactions": "^0.42.9",
22
+ "@0xsequence/utils": "^0.42.9",
23
+ "@0xsequence/wallet": "^0.42.9",
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
+ ]
@@ -1,7 +1,7 @@
1
1
  import { OpenWalletIntent, ProviderMessage, InitState, EventType, WindowSessionParams } from '../../types'
2
2
  import { BaseProviderTransport } from '../base-provider-transport'
3
3
  import { logger, base64EncodeObject } from '@0xsequence/utils'
4
- import { isBrowserExtension } from '../../utils'
4
+ import { isBrowserExtension, isUnityPlugin } from '../../utils'
5
5
 
6
6
  // ..
7
7
  let registeredWindowMessageProvider: WindowMessageProvider | undefined
@@ -92,7 +92,7 @@ export class WindowMessageProvider extends BaseProviderTransport {
92
92
 
93
93
  // skip setting origin host if we're in an browser extension execution context
94
94
  // allow origin that is passed in
95
- if (!isBrowserExtension()) {
95
+ if (!isBrowserExtension() && !isUnityPlugin()) {
96
96
  intent.options.origin = window.location.origin
97
97
  }
98
98
  }
@@ -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(address, encodeMessageDigest(prefixEIP191Message(message)), signature, chainId, walletContext)
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
- return ethers.utils.concat([eip191prefix, ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes])
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 (
@@ -86,6 +91,8 @@ export const recoverWalletConfig = async (
86
91
  export const isBrowserExtension = (): boolean =>
87
92
  window.location.protocol === 'chrome-extension:' || window.location.protocol === 'moz-extension:'
88
93
 
94
+ export const isUnityPlugin = (): boolean => !!navigator.userAgent.match(/UnitySequence/i)
95
+
89
96
  /**
90
97
  * Returns the status of a signer's wallet on given chain by checking wallet deployment and config status
91
98
  *