@reown/appkit-coinbase-react-native 0.0.0-accounts-canary.1-20251023174733

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.
Files changed (37) hide show
  1. package/lib/commonjs/connectors/CoinbaseConnector.js +136 -0
  2. package/lib/commonjs/connectors/CoinbaseConnector.js.map +1 -0
  3. package/lib/commonjs/index.js +13 -0
  4. package/lib/commonjs/index.js.map +1 -0
  5. package/lib/commonjs/package.json +1 -0
  6. package/lib/commonjs/providers/CoinbaseProvider.js +92 -0
  7. package/lib/commonjs/providers/CoinbaseProvider.js.map +1 -0
  8. package/lib/commonjs/types.js +6 -0
  9. package/lib/commonjs/types.js.map +1 -0
  10. package/lib/commonjs/utils.js +41 -0
  11. package/lib/commonjs/utils.js.map +1 -0
  12. package/lib/module/connectors/CoinbaseConnector.js +131 -0
  13. package/lib/module/connectors/CoinbaseConnector.js.map +1 -0
  14. package/lib/module/index.js +4 -0
  15. package/lib/module/index.js.map +1 -0
  16. package/lib/module/providers/CoinbaseProvider.js +86 -0
  17. package/lib/module/providers/CoinbaseProvider.js.map +1 -0
  18. package/lib/module/types.js +4 -0
  19. package/lib/module/types.js.map +1 -0
  20. package/lib/module/utils.js +36 -0
  21. package/lib/module/utils.js.map +1 -0
  22. package/lib/typescript/connectors/CoinbaseConnector.d.ts +22 -0
  23. package/lib/typescript/connectors/CoinbaseConnector.d.ts.map +1 -0
  24. package/lib/typescript/index.d.ts +3 -0
  25. package/lib/typescript/index.d.ts.map +1 -0
  26. package/lib/typescript/providers/CoinbaseProvider.d.ts +18 -0
  27. package/lib/typescript/providers/CoinbaseProvider.d.ts.map +1 -0
  28. package/lib/typescript/types.d.ts +17 -0
  29. package/lib/typescript/types.d.ts.map +1 -0
  30. package/lib/typescript/utils.d.ts +14 -0
  31. package/lib/typescript/utils.d.ts.map +1 -0
  32. package/package.json +51 -0
  33. package/src/connectors/CoinbaseConnector.ts +171 -0
  34. package/src/index.ts +2 -0
  35. package/src/providers/CoinbaseProvider.ts +106 -0
  36. package/src/types.ts +24 -0
  37. package/src/utils.ts +48 -0
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.CoinbaseConnector = void 0;
7
+ var _appkitCommonReactNative = require("@reown/appkit-common-react-native");
8
+ var _utils = require("../utils");
9
+ var _CoinbaseProvider = require("../providers/CoinbaseProvider");
10
+ const SESSION_KEY = '@appkit/coinbase-connector/session';
11
+ class CoinbaseConnector extends _appkitCommonReactNative.WalletConnector {
12
+ static SUPPORTED_NAMESPACE = 'eip155';
13
+ constructor(config) {
14
+ super({
15
+ type: 'coinbase'
16
+ });
17
+ this.config = config ?? {};
18
+ }
19
+ async init(ops) {
20
+ super.init(ops);
21
+ const redirect = ops.metadata.redirect?.universal ?? ops.metadata.redirect?.native;
22
+ if (!redirect) {
23
+ throw new Error('CoinbaseConnector: Redirect link not found in metadata');
24
+ }
25
+ this.provider = new _CoinbaseProvider.CoinbaseProvider({
26
+ redirect,
27
+ // use config storage, as it needs to be mmkv-compatible
28
+ storage: this.config.storage,
29
+ jsonRpcUrl: this.config.jsonRpcUrl
30
+ });
31
+ await this.restoreSession();
32
+ }
33
+ async connect(opts) {
34
+ const accounts = await this.getProvider().connect();
35
+ if (opts?.defaultNetwork && opts.defaultNetwork.chainNamespace === CoinbaseConnector.SUPPORTED_NAMESPACE) {
36
+ await this.switchNetwork(opts.defaultNetwork);
37
+ }
38
+ const namespaces = (0, _utils.getCoinbaseNamespace)(opts?.namespaces, accounts);
39
+ this.namespaces = namespaces;
40
+ this.saveSession(namespaces);
41
+ return this.namespaces;
42
+ }
43
+ async disconnect() {
44
+ await super.disconnect();
45
+ this.deleteSession();
46
+ }
47
+ getProvider() {
48
+ if (!this.provider) {
49
+ throw new Error('CoinbaseConnector: Provider not initialized. Call init() first.');
50
+ }
51
+ return this.provider;
52
+ }
53
+ getNamespaces() {
54
+ if (!this.namespaces) {
55
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
56
+ }
57
+ return this.namespaces;
58
+ }
59
+ getChainId() {
60
+ const hexChainId = this.getProvider().getChainId();
61
+ const chainId = _appkitCommonReactNative.StringUtil.hexToString(hexChainId);
62
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}`;
63
+ }
64
+ getWalletInfo() {
65
+ return {
66
+ name: 'Coinbase Wallet',
67
+ type: 'external'
68
+ };
69
+ }
70
+ getProperties() {
71
+ return undefined;
72
+ }
73
+ async switchNetwork(network) {
74
+ const provider = this.getProvider();
75
+ const chainId_ = _appkitCommonReactNative.NumberUtil.convertNumericToHexString(network.id);
76
+ try {
77
+ await provider.request({
78
+ method: 'wallet_switchEthereumChain',
79
+ params: [{
80
+ chainId: chainId_
81
+ }]
82
+ });
83
+ } catch (error) {
84
+ // Indicates chain is not added to provider
85
+ if (error?.code === 4902) {
86
+ try {
87
+ await provider.request({
88
+ method: 'wallet_addEthereumChain',
89
+ params: [{
90
+ chainId: chainId_,
91
+ chainName: network.name,
92
+ nativeCurrency: network.nativeCurrency,
93
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
94
+ blockExplorerUrls: [network.blockExplorers?.default.url]
95
+ }]
96
+ });
97
+ } catch (e) {
98
+ console.warn('CoinbaseConnector: switchNetwork error', e);
99
+ throw e;
100
+ }
101
+ }
102
+ console.warn('CoinbaseConnector: switchNetwork error', error);
103
+ throw error;
104
+ }
105
+ }
106
+ deleteSession() {
107
+ const storage = this.getStorage();
108
+ storage.removeItem(SESSION_KEY);
109
+ }
110
+ saveSession(namespaces) {
111
+ const storage = this.getStorage();
112
+ storage.setItem(SESSION_KEY, {
113
+ namespaces
114
+ });
115
+ }
116
+ async restoreSession() {
117
+ const storage = this.getStorage();
118
+ const session = await storage.getItem(SESSION_KEY);
119
+ if (!session) {
120
+ return false;
121
+ }
122
+ const {
123
+ namespaces
124
+ } = session;
125
+ this.namespaces = namespaces;
126
+ return true;
127
+ }
128
+ getStorage() {
129
+ if (!this.storage) {
130
+ throw new Error('CoinbaseConnector: Storage not initialized');
131
+ }
132
+ return this.storage;
133
+ }
134
+ }
135
+ exports.CoinbaseConnector = CoinbaseConnector;
136
+ //# sourceMappingURL=CoinbaseConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_appkitCommonReactNative","require","_utils","_CoinbaseProvider","SESSION_KEY","CoinbaseConnector","WalletConnector","SUPPORTED_NAMESPACE","constructor","config","type","init","ops","redirect","metadata","universal","native","Error","provider","CoinbaseProvider","storage","jsonRpcUrl","restoreSession","connect","opts","accounts","getProvider","defaultNetwork","chainNamespace","switchNetwork","namespaces","getCoinbaseNamespace","saveSession","disconnect","deleteSession","getNamespaces","getChainId","hexChainId","chainId","StringUtil","hexToString","getWalletInfo","name","getProperties","undefined","network","chainId_","NumberUtil","convertNumericToHexString","id","request","method","params","error","code","chainName","nativeCurrency","rpcUrls","default","http","blockExplorerUrls","blockExplorers","url","e","console","warn","getStorage","removeItem","setItem","session","getItem","exports"],"sourceRoot":"../../../src","sources":["connectors/CoinbaseConnector.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "CoinbaseConnector", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _CoinbaseConnector.CoinbaseConnector;
10
+ }
11
+ });
12
+ var _CoinbaseConnector = require("./connectors/CoinbaseConnector");
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_CoinbaseConnector","require"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;AAAA,IAAAA,kBAAA,GAAAC,OAAA","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.CoinbaseProvider = void 0;
7
+ var _events = _interopRequireDefault(require("events"));
8
+ var _appkitCommonReactNative = require("@reown/appkit-common-react-native");
9
+ var _walletMobileSdk = require("@coinbase/wallet-mobile-sdk");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ class CoinbaseProvider extends _events.default {
12
+ chainChangedListeners = new Map();
13
+ constructor(config) {
14
+ super();
15
+ this.config = config;
16
+ (0, _walletMobileSdk.configure)({
17
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
18
+ callbackURL: new URL(this.config.redirect),
19
+ // App Universal Link
20
+ hostPackageName: 'org.toshi'
21
+ });
22
+ this.provider = new _walletMobileSdk.WalletMobileSDKEVMProvider({
23
+ ...this.config,
24
+ jsonRpcUrl: this.config.jsonRpcUrl,
25
+ storage: this.config.storage
26
+ });
27
+ }
28
+ async connect() {
29
+ try {
30
+ let accounts = [];
31
+ const isConnected = this.provider.connected;
32
+ if (!isConnected) {
33
+ accounts = await this.provider.request({
34
+ method: 'eth_requestAccounts',
35
+ params: []
36
+ });
37
+ } else {
38
+ accounts = this.provider.selectedAddress ? [this.provider.selectedAddress] : [];
39
+ }
40
+ return accounts;
41
+ } catch (error) {
42
+ console.warn('CoinbaseProvider: connect error', error);
43
+ throw error;
44
+ }
45
+ }
46
+ async disconnect() {
47
+ this.provider.disconnect();
48
+ return Promise.resolve();
49
+ }
50
+ request(args) {
51
+ return this.provider.request(args);
52
+ }
53
+ getChainId() {
54
+ return this.provider.chainId;
55
+ }
56
+ onChainChanged(hexChainId) {
57
+ const chainId = _appkitCommonReactNative.StringUtil.hexToString(hexChainId);
58
+ this.emit('chainChanged', {
59
+ chainId
60
+ });
61
+ }
62
+ on(event, listener) {
63
+ if (event === 'chainChanged') {
64
+ // Create middleware that formats the chain ID before calling the original listener
65
+ const chainChangedMiddleware = hexChainId => {
66
+ const chainId = _appkitCommonReactNative.StringUtil.hexToString(hexChainId);
67
+ listener(chainId);
68
+ };
69
+
70
+ // Store the mapping between original listener and middleware
71
+ this.chainChangedListeners.set(listener, chainChangedMiddleware);
72
+ return this.provider.on('chainChanged', chainChangedMiddleware);
73
+ }
74
+ return this.provider.on(event, listener);
75
+ }
76
+ off(event, listener) {
77
+ if (event === 'chainChanged') {
78
+ // Get the middleware wrapper for this listener
79
+ const middleware = this.chainChangedListeners.get(listener);
80
+ if (middleware) {
81
+ // Remove the middleware from the provider
82
+ this.provider.off('chainChanged', middleware);
83
+ // Remove the mapping
84
+ this.chainChangedListeners.delete(listener);
85
+ return this;
86
+ }
87
+ }
88
+ return this.provider.off(event, listener);
89
+ }
90
+ }
91
+ exports.CoinbaseProvider = CoinbaseProvider;
92
+ //# sourceMappingURL=CoinbaseProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_events","_interopRequireDefault","require","_appkitCommonReactNative","_walletMobileSdk","e","__esModule","default","CoinbaseProvider","EventEmitter","chainChangedListeners","Map","constructor","config","configure","hostURL","URL","callbackURL","redirect","hostPackageName","provider","WalletMobileSDKEVMProvider","jsonRpcUrl","storage","connect","accounts","isConnected","connected","request","method","params","selectedAddress","error","console","warn","disconnect","Promise","resolve","args","getChainId","chainId","onChainChanged","hexChainId","StringUtil","hexToString","emit","on","event","listener","chainChangedMiddleware","set","off","middleware","get","delete","exports"],"sourceRoot":"../../../src","sources":["providers/CoinbaseProvider.ts"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,wBAAA,GAAAD,OAAA;AAKA,IAAAE,gBAAA,GAAAF,OAAA;AAAoF,SAAAD,uBAAAI,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAG7E,MAAMG,gBAAgB,SAASC,eAAY,CAAqB;EAG7DC,qBAAqB,GAAG,IAAIC,GAAG,CAGrC,CAAC;EAEHC,WAAWA,CAACC,MAA8B,EAAE;IAC1C,KAAK,CAAC,CAAC;IACP,IAAI,CAACA,MAAM,GAAGA,MAAM;IACpB,IAAAC,0BAAS,EAAC;MACRC,OAAO,EAAE,IAAIC,GAAG,CAAC,oCAAoC,CAAC;MACtDC,WAAW,EAAE,IAAID,GAAG,CAAC,IAAI,CAACH,MAAM,CAACK,QAAQ,CAAC;MAAE;MAC5CC,eAAe,EAAE;IACnB,CAAC,CAAC;IACF,IAAI,CAACC,QAAQ,GAAG,IAAIC,2CAA0B,CAAC;MAC7C,GAAG,IAAI,CAACR,MAAM;MACdS,UAAU,EAAE,IAAI,CAACT,MAAM,CAACS,UAAU;MAClCC,OAAO,EAAE,IAAI,CAACV,MAAM,CAACU;IACvB,CAAC,CAAC;EACJ;EAEA,MAAMC,OAAOA,CAAA,EAA6B;IACxC,IAAI;MACF,IAAIC,QAAkB,GAAG,EAAE;MAC3B,MAAMC,WAAW,GAAG,IAAI,CAACN,QAAQ,CAACO,SAAS;MAE3C,IAAI,CAACD,WAAW,EAAE;QAChBD,QAAQ,GAAG,MAAM,IAAI,CAACL,QAAQ,CAACQ,OAAO,CAAC;UACrCC,MAAM,EAAE,qBAAqB;UAC7BC,MAAM,EAAE;QACV,CAAC,CAAC;MACJ,CAAC,MAAM;QACLL,QAAQ,GAAG,IAAI,CAACL,QAAQ,CAACW,eAAe,GAAG,CAAC,IAAI,CAACX,QAAQ,CAACW,eAAe,CAAC,GAAG,EAAE;MACjF;MAEA,OAAON,QAAQ;IACjB,CAAC,CAAC,OAAOO,KAAK,EAAE;MACdC,OAAO,CAACC,IAAI,CAAC,iCAAiC,EAAEF,KAAK,CAAC;MAEtD,MAAMA,KAAK;IACb;EACF;EACA,MAAMG,UAAUA,CAAA,EAAkB;IAChC,IAAI,CAACf,QAAQ,CAACe,UAAU,CAAC,CAAC;IAE1B,OAAOC,OAAO,CAACC,OAAO,CAAC,CAAC;EAC1B;EAEAT,OAAOA,CAAcU,IAAsB,EAAc;IACvD,OAAO,IAAI,CAAClB,QAAQ,CAACQ,OAAO,CAACU,IAAI,CAAC;EACpC;EAEAC,UAAUA,CAAA,EAAkB;IAC1B,OAAO,IAAI,CAACnB,QAAQ,CAACoB,OAAO;EAC9B;EAEAC,cAAcA,CAACC,UAAyB,EAAQ;IAC9C,MAAMF,OAAO,GAAGG,mCAAU,CAACC,WAAW,CAACF,UAAU,CAAC;IAClD,IAAI,CAACG,IAAI,CAAC,cAAc,EAAE;MAAEL;IAAQ,CAAC,CAAC;EACxC;EAESM,EAAEA,CAACC,KAAa,EAAEC,QAA8B,EAAO;IAC9D,IAAID,KAAK,KAAK,cAAc,EAAE;MAC5B;MACA,MAAME,sBAAsB,GAAIP,UAAyB,IAAK;QAC5D,MAAMF,OAAO,GAAGG,mCAAU,CAACC,WAAW,CAACF,UAAU,CAAC;QAClDM,QAAQ,CAACR,OAAO,CAAC;MACnB,CAAC;;MAED;MACA,IAAI,CAAC9B,qBAAqB,CAACwC,GAAG,CAACF,QAAQ,EAAEC,sBAAsB,CAAC;MAEhE,OAAO,IAAI,CAAC7B,QAAQ,CAAC0B,EAAE,CAAC,cAAc,EAAEG,sBAAsB,CAAC;IACjE;IAEA,OAAO,IAAI,CAAC7B,QAAQ,CAAC0B,EAAE,CAACC,KAAK,EAAEC,QAAQ,CAAC;EAC1C;EAESG,GAAGA,CAACJ,KAAa,EAAEC,QAA8B,EAAO;IAC/D,IAAID,KAAK,KAAK,cAAc,EAAE;MAC5B;MACA,MAAMK,UAAU,GAAG,IAAI,CAAC1C,qBAAqB,CAAC2C,GAAG,CAACL,QAAQ,CAAC;MAC3D,IAAII,UAAU,EAAE;QACd;QACA,IAAI,CAAChC,QAAQ,CAAC+B,GAAG,CAAC,cAAc,EAAEC,UAAU,CAAC;QAC7C;QACA,IAAI,CAAC1C,qBAAqB,CAAC4C,MAAM,CAACN,QAAQ,CAAC;QAE3C,OAAO,IAAI;MACb;IACF;IAEA,OAAO,IAAI,CAAC5B,QAAQ,CAAC+B,GAAG,CAACJ,KAAK,EAAEC,QAAQ,CAAC;EAC3C;AACF;AAACO,OAAA,CAAA/C,gBAAA,GAAAA,gBAAA","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.COINBASE_METHODS = void 0;
7
+ exports.getCoinbaseNamespace = getCoinbaseNamespace;
8
+ const COINBASE_METHODS = exports.COINBASE_METHODS = {
9
+ REQUEST_ACCOUNTS: 'eth_requestAccounts',
10
+ SIGN_TRANSACTION: 'eth_signTransaction',
11
+ SEND_TRANSACTION: 'eth_sendTransaction',
12
+ SIGN_MESSAGE: 'personal_sign',
13
+ SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
14
+ SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
15
+ SWITCH_CHAIN: 'wallet_switchEthereumChain',
16
+ ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
17
+ WATCH_ASSET: 'wallet_watchAsset'
18
+ };
19
+ function getCoinbaseNamespace(namespaces, accounts) {
20
+ if (!namespaces || !accounts) {
21
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
22
+ }
23
+ const namespace = namespaces['eip155'];
24
+ if (!namespace) {
25
+ throw new Error('CoinbaseConnector: Namespace not found');
26
+ }
27
+ let caipAddresses = [];
28
+ for (const account of accounts) {
29
+ namespace.chains?.forEach(chain => {
30
+ caipAddresses.push(`${chain}:${account}`);
31
+ });
32
+ }
33
+ return {
34
+ ['eip155']: {
35
+ ...namespace,
36
+ methods: Object.values(COINBASE_METHODS),
37
+ accounts: caipAddresses
38
+ }
39
+ };
40
+ }
41
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["COINBASE_METHODS","exports","REQUEST_ACCOUNTS","SIGN_TRANSACTION","SEND_TRANSACTION","SIGN_MESSAGE","SIGN_TYPED_DATA_V3","SIGN_TYPED_DATA_V4","SWITCH_CHAIN","ADD_ETHEREUM_CHAIN","WATCH_ASSET","getCoinbaseNamespace","namespaces","accounts","Error","namespace","caipAddresses","account","chains","forEach","chain","push","methods","Object","values"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":";;;;;;;AAMO,MAAMA,gBAAgB,GAAAC,OAAA,CAAAD,gBAAA,GAAG;EAC9BE,gBAAgB,EAAE,qBAAqB;EACvCC,gBAAgB,EAAE,qBAAqB;EACvCC,gBAAgB,EAAE,qBAAqB;EACvCC,YAAY,EAAE,eAAe;EAC7BC,kBAAkB,EAAE,sBAAsB;EAC1CC,kBAAkB,EAAE,sBAAsB;EAC1CC,YAAY,EAAE,4BAA4B;EAC1CC,kBAAkB,EAAE,yBAAyB;EAC7CC,WAAW,EAAE;AACf,CAAU;AAEH,SAASC,oBAAoBA,CAClCC,UAA+B,EAC/BC,QAAmB,EACP;EACZ,IAAI,CAACD,UAAU,IAAI,CAACC,QAAQ,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,qDAAqD,CAAC;EACxE;EAEA,MAAMC,SAAS,GAAGH,UAAU,CAAC,QAAQ,CAAC;EAEtC,IAAI,CAACG,SAAS,EAAE;IACd,MAAM,IAAID,KAAK,CAAC,wCAAwC,CAAC;EAC3D;EAEA,IAAIE,aAA4B,GAAG,EAAE;EAErC,KAAK,MAAMC,OAAO,IAAIJ,QAAQ,EAAE;IAC9BE,SAAS,CAACG,MAAM,EAAEC,OAAO,CAACC,KAAK,IAAI;MACjCJ,aAAa,CAACK,IAAI,CAAC,GAAGD,KAAK,IAAIH,OAAO,EAAE,CAAC;IAC3C,CAAC,CAAC;EACJ;EAEA,OAAO;IACL,CAAC,QAAQ,GAAG;MACV,GAAGF,SAAS;MACZO,OAAO,EAAEC,MAAM,CAACC,MAAM,CAACxB,gBAAgB,CAAC;MACxCa,QAAQ,EAAEG;IACZ;EACF,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+
3
+ import { WalletConnector, NumberUtil, StringUtil } from '@reown/appkit-common-react-native';
4
+ import { getCoinbaseNamespace } from '../utils';
5
+ import { CoinbaseProvider } from '../providers/CoinbaseProvider';
6
+ const SESSION_KEY = '@appkit/coinbase-connector/session';
7
+ export class CoinbaseConnector extends WalletConnector {
8
+ static SUPPORTED_NAMESPACE = 'eip155';
9
+ constructor(config) {
10
+ super({
11
+ type: 'coinbase'
12
+ });
13
+ this.config = config ?? {};
14
+ }
15
+ async init(ops) {
16
+ super.init(ops);
17
+ const redirect = ops.metadata.redirect?.universal ?? ops.metadata.redirect?.native;
18
+ if (!redirect) {
19
+ throw new Error('CoinbaseConnector: Redirect link not found in metadata');
20
+ }
21
+ this.provider = new CoinbaseProvider({
22
+ redirect,
23
+ // use config storage, as it needs to be mmkv-compatible
24
+ storage: this.config.storage,
25
+ jsonRpcUrl: this.config.jsonRpcUrl
26
+ });
27
+ await this.restoreSession();
28
+ }
29
+ async connect(opts) {
30
+ const accounts = await this.getProvider().connect();
31
+ if (opts?.defaultNetwork && opts.defaultNetwork.chainNamespace === CoinbaseConnector.SUPPORTED_NAMESPACE) {
32
+ await this.switchNetwork(opts.defaultNetwork);
33
+ }
34
+ const namespaces = getCoinbaseNamespace(opts?.namespaces, accounts);
35
+ this.namespaces = namespaces;
36
+ this.saveSession(namespaces);
37
+ return this.namespaces;
38
+ }
39
+ async disconnect() {
40
+ await super.disconnect();
41
+ this.deleteSession();
42
+ }
43
+ getProvider() {
44
+ if (!this.provider) {
45
+ throw new Error('CoinbaseConnector: Provider not initialized. Call init() first.');
46
+ }
47
+ return this.provider;
48
+ }
49
+ getNamespaces() {
50
+ if (!this.namespaces) {
51
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
52
+ }
53
+ return this.namespaces;
54
+ }
55
+ getChainId() {
56
+ const hexChainId = this.getProvider().getChainId();
57
+ const chainId = StringUtil.hexToString(hexChainId);
58
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}`;
59
+ }
60
+ getWalletInfo() {
61
+ return {
62
+ name: 'Coinbase Wallet',
63
+ type: 'external'
64
+ };
65
+ }
66
+ getProperties() {
67
+ return undefined;
68
+ }
69
+ async switchNetwork(network) {
70
+ const provider = this.getProvider();
71
+ const chainId_ = NumberUtil.convertNumericToHexString(network.id);
72
+ try {
73
+ await provider.request({
74
+ method: 'wallet_switchEthereumChain',
75
+ params: [{
76
+ chainId: chainId_
77
+ }]
78
+ });
79
+ } catch (error) {
80
+ // Indicates chain is not added to provider
81
+ if (error?.code === 4902) {
82
+ try {
83
+ await provider.request({
84
+ method: 'wallet_addEthereumChain',
85
+ params: [{
86
+ chainId: chainId_,
87
+ chainName: network.name,
88
+ nativeCurrency: network.nativeCurrency,
89
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
90
+ blockExplorerUrls: [network.blockExplorers?.default.url]
91
+ }]
92
+ });
93
+ } catch (e) {
94
+ console.warn('CoinbaseConnector: switchNetwork error', e);
95
+ throw e;
96
+ }
97
+ }
98
+ console.warn('CoinbaseConnector: switchNetwork error', error);
99
+ throw error;
100
+ }
101
+ }
102
+ deleteSession() {
103
+ const storage = this.getStorage();
104
+ storage.removeItem(SESSION_KEY);
105
+ }
106
+ saveSession(namespaces) {
107
+ const storage = this.getStorage();
108
+ storage.setItem(SESSION_KEY, {
109
+ namespaces
110
+ });
111
+ }
112
+ async restoreSession() {
113
+ const storage = this.getStorage();
114
+ const session = await storage.getItem(SESSION_KEY);
115
+ if (!session) {
116
+ return false;
117
+ }
118
+ const {
119
+ namespaces
120
+ } = session;
121
+ this.namespaces = namespaces;
122
+ return true;
123
+ }
124
+ getStorage() {
125
+ if (!this.storage) {
126
+ throw new Error('CoinbaseConnector: Storage not initialized');
127
+ }
128
+ return this.storage;
129
+ }
130
+ }
131
+ //# sourceMappingURL=CoinbaseConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WalletConnector","NumberUtil","StringUtil","getCoinbaseNamespace","CoinbaseProvider","SESSION_KEY","CoinbaseConnector","SUPPORTED_NAMESPACE","constructor","config","type","init","ops","redirect","metadata","universal","native","Error","provider","storage","jsonRpcUrl","restoreSession","connect","opts","accounts","getProvider","defaultNetwork","chainNamespace","switchNetwork","namespaces","saveSession","disconnect","deleteSession","getNamespaces","getChainId","hexChainId","chainId","hexToString","getWalletInfo","name","getProperties","undefined","network","chainId_","convertNumericToHexString","id","request","method","params","error","code","chainName","nativeCurrency","rpcUrls","default","http","blockExplorerUrls","blockExplorers","url","e","console","warn","getStorage","removeItem","setItem","session","getItem"],"sourceRoot":"../../../src","sources":["connectors/CoinbaseConnector.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { CoinbaseConnector } from './connectors/CoinbaseConnector';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["CoinbaseConnector"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,iBAAiB,QAAQ,gCAAgC","ignoreList":[]}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+
3
+ import EventEmitter from 'events';
4
+ import { StringUtil } from '@reown/appkit-common-react-native';
5
+ import { configure, WalletMobileSDKEVMProvider } from '@coinbase/wallet-mobile-sdk';
6
+ export class CoinbaseProvider extends EventEmitter {
7
+ chainChangedListeners = new Map();
8
+ constructor(config) {
9
+ super();
10
+ this.config = config;
11
+ configure({
12
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
13
+ callbackURL: new URL(this.config.redirect),
14
+ // App Universal Link
15
+ hostPackageName: 'org.toshi'
16
+ });
17
+ this.provider = new WalletMobileSDKEVMProvider({
18
+ ...this.config,
19
+ jsonRpcUrl: this.config.jsonRpcUrl,
20
+ storage: this.config.storage
21
+ });
22
+ }
23
+ async connect() {
24
+ try {
25
+ let accounts = [];
26
+ const isConnected = this.provider.connected;
27
+ if (!isConnected) {
28
+ accounts = await this.provider.request({
29
+ method: 'eth_requestAccounts',
30
+ params: []
31
+ });
32
+ } else {
33
+ accounts = this.provider.selectedAddress ? [this.provider.selectedAddress] : [];
34
+ }
35
+ return accounts;
36
+ } catch (error) {
37
+ console.warn('CoinbaseProvider: connect error', error);
38
+ throw error;
39
+ }
40
+ }
41
+ async disconnect() {
42
+ this.provider.disconnect();
43
+ return Promise.resolve();
44
+ }
45
+ request(args) {
46
+ return this.provider.request(args);
47
+ }
48
+ getChainId() {
49
+ return this.provider.chainId;
50
+ }
51
+ onChainChanged(hexChainId) {
52
+ const chainId = StringUtil.hexToString(hexChainId);
53
+ this.emit('chainChanged', {
54
+ chainId
55
+ });
56
+ }
57
+ on(event, listener) {
58
+ if (event === 'chainChanged') {
59
+ // Create middleware that formats the chain ID before calling the original listener
60
+ const chainChangedMiddleware = hexChainId => {
61
+ const chainId = StringUtil.hexToString(hexChainId);
62
+ listener(chainId);
63
+ };
64
+
65
+ // Store the mapping between original listener and middleware
66
+ this.chainChangedListeners.set(listener, chainChangedMiddleware);
67
+ return this.provider.on('chainChanged', chainChangedMiddleware);
68
+ }
69
+ return this.provider.on(event, listener);
70
+ }
71
+ off(event, listener) {
72
+ if (event === 'chainChanged') {
73
+ // Get the middleware wrapper for this listener
74
+ const middleware = this.chainChangedListeners.get(listener);
75
+ if (middleware) {
76
+ // Remove the middleware from the provider
77
+ this.provider.off('chainChanged', middleware);
78
+ // Remove the mapping
79
+ this.chainChangedListeners.delete(listener);
80
+ return this;
81
+ }
82
+ }
83
+ return this.provider.off(event, listener);
84
+ }
85
+ }
86
+ //# sourceMappingURL=CoinbaseProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["EventEmitter","StringUtil","configure","WalletMobileSDKEVMProvider","CoinbaseProvider","chainChangedListeners","Map","constructor","config","hostURL","URL","callbackURL","redirect","hostPackageName","provider","jsonRpcUrl","storage","connect","accounts","isConnected","connected","request","method","params","selectedAddress","error","console","warn","disconnect","Promise","resolve","args","getChainId","chainId","onChainChanged","hexChainId","hexToString","emit","on","event","listener","chainChangedMiddleware","set","off","middleware","get","delete"],"sourceRoot":"../../../src","sources":["providers/CoinbaseProvider.ts"],"mappings":";;AAAA,OAAOA,YAAY,MAAM,QAAQ;AACjC,SAGEC,UAAU,QACL,mCAAmC;AAC1C,SAASC,SAAS,EAAEC,0BAA0B,QAAQ,6BAA6B;AAGnF,OAAO,MAAMC,gBAAgB,SAASJ,YAAY,CAAqB;EAG7DK,qBAAqB,GAAG,IAAIC,GAAG,CAGrC,CAAC;EAEHC,WAAWA,CAACC,MAA8B,EAAE;IAC1C,KAAK,CAAC,CAAC;IACP,IAAI,CAACA,MAAM,GAAGA,MAAM;IACpBN,SAAS,CAAC;MACRO,OAAO,EAAE,IAAIC,GAAG,CAAC,oCAAoC,CAAC;MACtDC,WAAW,EAAE,IAAID,GAAG,CAAC,IAAI,CAACF,MAAM,CAACI,QAAQ,CAAC;MAAE;MAC5CC,eAAe,EAAE;IACnB,CAAC,CAAC;IACF,IAAI,CAACC,QAAQ,GAAG,IAAIX,0BAA0B,CAAC;MAC7C,GAAG,IAAI,CAACK,MAAM;MACdO,UAAU,EAAE,IAAI,CAACP,MAAM,CAACO,UAAU;MAClCC,OAAO,EAAE,IAAI,CAACR,MAAM,CAACQ;IACvB,CAAC,CAAC;EACJ;EAEA,MAAMC,OAAOA,CAAA,EAA6B;IACxC,IAAI;MACF,IAAIC,QAAkB,GAAG,EAAE;MAC3B,MAAMC,WAAW,GAAG,IAAI,CAACL,QAAQ,CAACM,SAAS;MAE3C,IAAI,CAACD,WAAW,EAAE;QAChBD,QAAQ,GAAG,MAAM,IAAI,CAACJ,QAAQ,CAACO,OAAO,CAAC;UACrCC,MAAM,EAAE,qBAAqB;UAC7BC,MAAM,EAAE;QACV,CAAC,CAAC;MACJ,CAAC,MAAM;QACLL,QAAQ,GAAG,IAAI,CAACJ,QAAQ,CAACU,eAAe,GAAG,CAAC,IAAI,CAACV,QAAQ,CAACU,eAAe,CAAC,GAAG,EAAE;MACjF;MAEA,OAAON,QAAQ;IACjB,CAAC,CAAC,OAAOO,KAAK,EAAE;MACdC,OAAO,CAACC,IAAI,CAAC,iCAAiC,EAAEF,KAAK,CAAC;MAEtD,MAAMA,KAAK;IACb;EACF;EACA,MAAMG,UAAUA,CAAA,EAAkB;IAChC,IAAI,CAACd,QAAQ,CAACc,UAAU,CAAC,CAAC;IAE1B,OAAOC,OAAO,CAACC,OAAO,CAAC,CAAC;EAC1B;EAEAT,OAAOA,CAAcU,IAAsB,EAAc;IACvD,OAAO,IAAI,CAACjB,QAAQ,CAACO,OAAO,CAACU,IAAI,CAAC;EACpC;EAEAC,UAAUA,CAAA,EAAkB;IAC1B,OAAO,IAAI,CAAClB,QAAQ,CAACmB,OAAO;EAC9B;EAEAC,cAAcA,CAACC,UAAyB,EAAQ;IAC9C,MAAMF,OAAO,GAAGhC,UAAU,CAACmC,WAAW,CAACD,UAAU,CAAC;IAClD,IAAI,CAACE,IAAI,CAAC,cAAc,EAAE;MAAEJ;IAAQ,CAAC,CAAC;EACxC;EAESK,EAAEA,CAACC,KAAa,EAAEC,QAA8B,EAAO;IAC9D,IAAID,KAAK,KAAK,cAAc,EAAE;MAC5B;MACA,MAAME,sBAAsB,GAAIN,UAAyB,IAAK;QAC5D,MAAMF,OAAO,GAAGhC,UAAU,CAACmC,WAAW,CAACD,UAAU,CAAC;QAClDK,QAAQ,CAACP,OAAO,CAAC;MACnB,CAAC;;MAED;MACA,IAAI,CAAC5B,qBAAqB,CAACqC,GAAG,CAACF,QAAQ,EAAEC,sBAAsB,CAAC;MAEhE,OAAO,IAAI,CAAC3B,QAAQ,CAACwB,EAAE,CAAC,cAAc,EAAEG,sBAAsB,CAAC;IACjE;IAEA,OAAO,IAAI,CAAC3B,QAAQ,CAACwB,EAAE,CAACC,KAAK,EAAEC,QAAQ,CAAC;EAC1C;EAESG,GAAGA,CAACJ,KAAa,EAAEC,QAA8B,EAAO;IAC/D,IAAID,KAAK,KAAK,cAAc,EAAE;MAC5B;MACA,MAAMK,UAAU,GAAG,IAAI,CAACvC,qBAAqB,CAACwC,GAAG,CAACL,QAAQ,CAAC;MAC3D,IAAII,UAAU,EAAE;QACd;QACA,IAAI,CAAC9B,QAAQ,CAAC6B,GAAG,CAAC,cAAc,EAAEC,UAAU,CAAC;QAC7C;QACA,IAAI,CAACvC,qBAAqB,CAACyC,MAAM,CAACN,QAAQ,CAAC;QAE3C,OAAO,IAAI;MACb;IACF;IAEA,OAAO,IAAI,CAAC1B,QAAQ,CAAC6B,GAAG,CAACJ,KAAK,EAAEC,QAAQ,CAAC;EAC3C;AACF","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ export const COINBASE_METHODS = {
4
+ REQUEST_ACCOUNTS: 'eth_requestAccounts',
5
+ SIGN_TRANSACTION: 'eth_signTransaction',
6
+ SEND_TRANSACTION: 'eth_sendTransaction',
7
+ SIGN_MESSAGE: 'personal_sign',
8
+ SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
9
+ SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
10
+ SWITCH_CHAIN: 'wallet_switchEthereumChain',
11
+ ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
12
+ WATCH_ASSET: 'wallet_watchAsset'
13
+ };
14
+ export function getCoinbaseNamespace(namespaces, accounts) {
15
+ if (!namespaces || !accounts) {
16
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
17
+ }
18
+ const namespace = namespaces['eip155'];
19
+ if (!namespace) {
20
+ throw new Error('CoinbaseConnector: Namespace not found');
21
+ }
22
+ let caipAddresses = [];
23
+ for (const account of accounts) {
24
+ namespace.chains?.forEach(chain => {
25
+ caipAddresses.push(`${chain}:${account}`);
26
+ });
27
+ }
28
+ return {
29
+ ['eip155']: {
30
+ ...namespace,
31
+ methods: Object.values(COINBASE_METHODS),
32
+ accounts: caipAddresses
33
+ }
34
+ };
35
+ }
36
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["COINBASE_METHODS","REQUEST_ACCOUNTS","SIGN_TRANSACTION","SEND_TRANSACTION","SIGN_MESSAGE","SIGN_TYPED_DATA_V3","SIGN_TYPED_DATA_V4","SWITCH_CHAIN","ADD_ETHEREUM_CHAIN","WATCH_ASSET","getCoinbaseNamespace","namespaces","accounts","Error","namespace","caipAddresses","account","chains","forEach","chain","push","methods","Object","values"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":";;AAMA,OAAO,MAAMA,gBAAgB,GAAG;EAC9BC,gBAAgB,EAAE,qBAAqB;EACvCC,gBAAgB,EAAE,qBAAqB;EACvCC,gBAAgB,EAAE,qBAAqB;EACvCC,YAAY,EAAE,eAAe;EAC7BC,kBAAkB,EAAE,sBAAsB;EAC1CC,kBAAkB,EAAE,sBAAsB;EAC1CC,YAAY,EAAE,4BAA4B;EAC1CC,kBAAkB,EAAE,yBAAyB;EAC7CC,WAAW,EAAE;AACf,CAAU;AAEV,OAAO,SAASC,oBAAoBA,CAClCC,UAA+B,EAC/BC,QAAmB,EACP;EACZ,IAAI,CAACD,UAAU,IAAI,CAACC,QAAQ,EAAE;IAC5B,MAAM,IAAIC,KAAK,CAAC,qDAAqD,CAAC;EACxE;EAEA,MAAMC,SAAS,GAAGH,UAAU,CAAC,QAAQ,CAAC;EAEtC,IAAI,CAACG,SAAS,EAAE;IACd,MAAM,IAAID,KAAK,CAAC,wCAAwC,CAAC;EAC3D;EAEA,IAAIE,aAA4B,GAAG,EAAE;EAErC,KAAK,MAAMC,OAAO,IAAIJ,QAAQ,EAAE;IAC9BE,SAAS,CAACG,MAAM,EAAEC,OAAO,CAACC,KAAK,IAAI;MACjCJ,aAAa,CAACK,IAAI,CAAC,GAAGD,KAAK,IAAIH,OAAO,EAAE,CAAC;IAC3C,CAAC,CAAC;EACJ;EAEA,OAAO;IACL,CAAC,QAAQ,GAAG;MACV,GAAGF,SAAS;MACZO,OAAO,EAAEC,MAAM,CAACC,MAAM,CAACvB,gBAAgB,CAAC;MACxCY,QAAQ,EAAEG;IACZ;EACF,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,22 @@
1
+ import { WalletConnector, type AppKitNetwork, type CaipNetworkId, type ConnectionProperties, type ConnectOptions, type ConnectorInitOptions, type Namespaces, type WalletInfo } from '@reown/appkit-common-react-native';
2
+ import { CoinbaseProvider } from '../providers/CoinbaseProvider';
3
+ import type { CoinbaseConnectorConfig } from '../types';
4
+ export declare class CoinbaseConnector extends WalletConnector {
5
+ private static readonly SUPPORTED_NAMESPACE;
6
+ private config;
7
+ constructor(config?: CoinbaseConnectorConfig);
8
+ init(ops: ConnectorInitOptions): Promise<void>;
9
+ connect(opts?: Pick<ConnectOptions, 'namespaces' | 'defaultNetwork'>): Promise<Namespaces | undefined>;
10
+ disconnect(): Promise<void>;
11
+ getProvider(): CoinbaseProvider;
12
+ getNamespaces(): Namespaces;
13
+ getChainId(): CaipNetworkId | undefined;
14
+ getWalletInfo(): WalletInfo | undefined;
15
+ getProperties(): ConnectionProperties | undefined;
16
+ switchNetwork(network: AppKitNetwork): Promise<void>;
17
+ private deleteSession;
18
+ private saveSession;
19
+ restoreSession(): Promise<boolean>;
20
+ private getStorage;
21
+ }
22
+ //# sourceMappingURL=CoinbaseConnector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoinbaseConnector.d.ts","sourceRoot":"","sources":["../../../src/connectors/CoinbaseConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAElB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,UAAU,EAIhB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,uBAAuB,EAAmB,MAAM,UAAU,CAAC;AAIzE,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAA4B;IACvE,OAAO,CAAC,MAAM,CAA0B;gBAE5B,MAAM,CAAC,EAAE,uBAAuB;IAK7B,IAAI,CAAC,GAAG,EAAE,oBAAoB;IAkB9B,OAAO,CACpB,IAAI,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,GAAG,gBAAgB,CAAC,GAC3D,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAiBnB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC,WAAW,IAAI,gBAAgB;IAQ/B,aAAa,IAAI,UAAU;IAQ3B,UAAU,IAAI,aAAa,GAAG,SAAS;IAOvC,aAAa,IAAI,UAAU,GAAG,SAAS;IAOvC,aAAa,IAAI,oBAAoB,GAAG,SAAS;IAI3C,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCnE,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,WAAW;IAKJ,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAajD,OAAO,CAAC,UAAU;CAOnB"}
@@ -0,0 +1,3 @@
1
+ export { CoinbaseConnector } from './connectors/CoinbaseConnector';
2
+ export type { CoinbaseConnectorConfig } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,YAAY,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,18 @@
1
+ /// <reference types="node" />
2
+ import EventEmitter from 'events';
3
+ import { type Provider, type RequestArguments } from '@reown/appkit-common-react-native';
4
+ import type { CoinbaseProviderConfig } from '../types';
5
+ export declare class CoinbaseProvider extends EventEmitter implements Provider {
6
+ private readonly config;
7
+ private provider;
8
+ private chainChangedListeners;
9
+ constructor(config: CoinbaseProviderConfig);
10
+ connect<T = string[]>(): Promise<T>;
11
+ disconnect(): Promise<void>;
12
+ request<T = unknown>(args: RequestArguments): Promise<T>;
13
+ getChainId(): `0x${string}`;
14
+ onChainChanged(hexChainId: `0x${string}`): void;
15
+ on(event: string, listener: (args?: any) => void): any;
16
+ off(event: string, listener: (args?: any) => void): any;
17
+ }
18
+ //# sourceMappingURL=CoinbaseProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoinbaseProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/CoinbaseProvider.ts"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEvD,qBAAa,gBAAiB,SAAQ,YAAa,YAAW,QAAQ;IACpE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,qBAAqB,CAGzB;gBAEQ,MAAM,EAAE,sBAAsB;IAepC,OAAO,CAAC,CAAC,GAAG,MAAM,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC;IAqBnC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAIxD,UAAU,IAAI,KAAK,MAAM,EAAE;IAI3B,cAAc,CAAC,UAAU,EAAE,KAAK,MAAM,EAAE,GAAG,IAAI;IAKtC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG;IAiBtD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG;CAgBjE"}
@@ -0,0 +1,17 @@
1
+ import type { MMKV } from 'react-native-mmkv';
2
+ import type { Namespaces } from '@reown/appkit-common-react-native';
3
+ import type { KVStorage, WalletMobileSDKProviderOptions } from '@coinbase/wallet-mobile-sdk/build/WalletMobileSDKEVMProvider';
4
+ import type { COINBASE_METHODS } from './utils';
5
+ export type CoinbaseProviderConfig = Omit<WalletMobileSDKProviderOptions, 'chainId' | 'address'> & {
6
+ redirect: string;
7
+ };
8
+ export type Values<T> = T[keyof T];
9
+ export type CoinbaseMethod = Values<typeof COINBASE_METHODS>;
10
+ export type CoinbaseSession = {
11
+ namespaces: Namespaces;
12
+ };
13
+ export type CoinbaseConnectorConfig = {
14
+ storage?: KVStorage | MMKV;
15
+ jsonRpcUrl?: string;
16
+ };
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,KAAK,EACV,SAAS,EACT,8BAA8B,EAC/B,MAAM,8DAA8D,CAAC;AACtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,8BAA8B,EAAE,SAAS,GAAG,SAAS,CAAC,GAAG;IACjG,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEnC,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Namespaces, ProposalNamespaces } from '@reown/appkit-common-react-native';
2
+ export declare const COINBASE_METHODS: {
3
+ readonly REQUEST_ACCOUNTS: "eth_requestAccounts";
4
+ readonly SIGN_TRANSACTION: "eth_signTransaction";
5
+ readonly SEND_TRANSACTION: "eth_sendTransaction";
6
+ readonly SIGN_MESSAGE: "personal_sign";
7
+ readonly SIGN_TYPED_DATA_V3: "eth_signTypedData_v3";
8
+ readonly SIGN_TYPED_DATA_V4: "eth_signTypedData_v4";
9
+ readonly SWITCH_CHAIN: "wallet_switchEthereumChain";
10
+ readonly ADD_ETHEREUM_CHAIN: "wallet_addEthereumChain";
11
+ readonly WATCH_ASSET: "wallet_watchAsset";
12
+ };
13
+ export declare function getCoinbaseNamespace(namespaces?: ProposalNamespaces, accounts?: string[]): Namespaces;
14
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,UAAU,EACV,kBAAkB,EACnB,MAAM,mCAAmC,CAAC;AAE3C,eAAO,MAAM,gBAAgB;;;;;;;;;;CAUnB,CAAC;AAEX,wBAAgB,oBAAoB,CAClC,UAAU,CAAC,EAAE,kBAAkB,EAC/B,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,UAAU,CA0BZ"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@reown/appkit-coinbase-react-native",
3
+ "version": "0.0.0-accounts-canary.1-20251023174733",
4
+ "main": "lib/commonjs/index.js",
5
+ "types": "lib/typescript/index.d.ts",
6
+ "module": "lib/module/index.js",
7
+ "react-native": "src/index.ts",
8
+ "source": "src/index.ts",
9
+ "scripts": {
10
+ "build": "bob build",
11
+ "clean": "rm -rf lib",
12
+ "test": "jest --passWithNoTests",
13
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib"
18
+ ],
19
+ "keywords": [
20
+ "web3",
21
+ "crypto",
22
+ "appkit",
23
+ "walletconnect",
24
+ "react-native",
25
+ "coinbase"
26
+ ],
27
+ "repository": "https://github.com/reown-com/appkit-react-native",
28
+ "author": "Reown (https://discord.gg/reown)",
29
+ "homepage": "https://reown.com/appkit",
30
+ "license": "SEE LICENSE IN LICENSE.md",
31
+ "bugs": {
32
+ "url": "https://github.com/reown-com/appkit-react-native/issues"
33
+ },
34
+ "publishConfig": {
35
+ "registry": "https://registry.npmjs.org/",
36
+ "access": "public",
37
+ "provenance": true
38
+ },
39
+ "dependencies": {
40
+ "@reown/appkit-common-react-native": "0.0.0-accounts-canary.1-20251023174733"
41
+ },
42
+ "peerDependencies": {
43
+ "@coinbase/wallet-mobile-sdk": ">=1.1.2",
44
+ "react": ">=18",
45
+ "react-native": ">=0.72"
46
+ },
47
+ "eslintIgnore": [
48
+ "node_modules/",
49
+ "lib/"
50
+ ]
51
+ }
@@ -0,0 +1,171 @@
1
+ import {
2
+ WalletConnector,
3
+ type AppKitNetwork,
4
+ type CaipNetworkId,
5
+ type ChainNamespace,
6
+ type ConnectionProperties,
7
+ type ConnectOptions,
8
+ type ConnectorInitOptions,
9
+ type Namespaces,
10
+ type WalletInfo,
11
+ type Storage,
12
+ NumberUtil,
13
+ StringUtil
14
+ } from '@reown/appkit-common-react-native';
15
+ import { getCoinbaseNamespace } from '../utils';
16
+ import { CoinbaseProvider } from '../providers/CoinbaseProvider';
17
+ import type { CoinbaseConnectorConfig, CoinbaseSession } from '../types';
18
+
19
+ const SESSION_KEY = '@appkit/coinbase-connector/session';
20
+
21
+ export class CoinbaseConnector extends WalletConnector {
22
+ private static readonly SUPPORTED_NAMESPACE: ChainNamespace = 'eip155';
23
+ private config: CoinbaseConnectorConfig;
24
+
25
+ constructor(config?: CoinbaseConnectorConfig) {
26
+ super({ type: 'coinbase' });
27
+ this.config = config ?? {};
28
+ }
29
+
30
+ override async init(ops: ConnectorInitOptions) {
31
+ super.init(ops);
32
+
33
+ const redirect = ops.metadata.redirect?.universal ?? ops.metadata.redirect?.native;
34
+ if (!redirect) {
35
+ throw new Error('CoinbaseConnector: Redirect link not found in metadata');
36
+ }
37
+
38
+ this.provider = new CoinbaseProvider({
39
+ redirect,
40
+ // use config storage, as it needs to be mmkv-compatible
41
+ storage: this.config.storage,
42
+ jsonRpcUrl: this.config.jsonRpcUrl
43
+ });
44
+
45
+ await this.restoreSession();
46
+ }
47
+
48
+ override async connect(
49
+ opts?: Pick<ConnectOptions, 'namespaces' | 'defaultNetwork'>
50
+ ): Promise<Namespaces | undefined> {
51
+ const accounts = await this.getProvider().connect();
52
+
53
+ if (
54
+ opts?.defaultNetwork &&
55
+ opts.defaultNetwork.chainNamespace === CoinbaseConnector.SUPPORTED_NAMESPACE
56
+ ) {
57
+ await this.switchNetwork(opts.defaultNetwork);
58
+ }
59
+
60
+ const namespaces = getCoinbaseNamespace(opts?.namespaces, accounts);
61
+ this.namespaces = namespaces;
62
+ this.saveSession(namespaces);
63
+
64
+ return this.namespaces;
65
+ }
66
+
67
+ override async disconnect(): Promise<void> {
68
+ await super.disconnect();
69
+ this.deleteSession();
70
+ }
71
+
72
+ override getProvider(): CoinbaseProvider {
73
+ if (!this.provider) {
74
+ throw new Error('CoinbaseConnector: Provider not initialized. Call init() first.');
75
+ }
76
+
77
+ return this.provider as CoinbaseProvider;
78
+ }
79
+
80
+ override getNamespaces(): Namespaces {
81
+ if (!this.namespaces) {
82
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
83
+ }
84
+
85
+ return this.namespaces;
86
+ }
87
+
88
+ override getChainId(): CaipNetworkId | undefined {
89
+ const hexChainId = this.getProvider().getChainId();
90
+ const chainId = StringUtil.hexToString(hexChainId);
91
+
92
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}` as CaipNetworkId;
93
+ }
94
+
95
+ override getWalletInfo(): WalletInfo | undefined {
96
+ return {
97
+ name: 'Coinbase Wallet',
98
+ type: 'external'
99
+ };
100
+ }
101
+
102
+ override getProperties(): ConnectionProperties | undefined {
103
+ return undefined;
104
+ }
105
+
106
+ override async switchNetwork(network: AppKitNetwork): Promise<void> {
107
+ const provider = this.getProvider();
108
+ const chainId_ = NumberUtil.convertNumericToHexString(network.id);
109
+
110
+ try {
111
+ await provider.request({
112
+ method: 'wallet_switchEthereumChain',
113
+ params: [{ chainId: chainId_ }]
114
+ });
115
+ } catch (error: any) {
116
+ // Indicates chain is not added to provider
117
+ if (error?.code === 4902) {
118
+ try {
119
+ await provider.request({
120
+ method: 'wallet_addEthereumChain',
121
+ params: [
122
+ {
123
+ chainId: chainId_,
124
+ chainName: network.name,
125
+ nativeCurrency: network.nativeCurrency,
126
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
127
+ blockExplorerUrls: [network.blockExplorers?.default.url]
128
+ }
129
+ ]
130
+ });
131
+ } catch (e) {
132
+ console.warn('CoinbaseConnector: switchNetwork error', e);
133
+ throw e;
134
+ }
135
+ }
136
+ console.warn('CoinbaseConnector: switchNetwork error', error);
137
+ throw error;
138
+ }
139
+ }
140
+
141
+ private deleteSession(): void {
142
+ const storage = this.getStorage();
143
+ storage.removeItem(SESSION_KEY);
144
+ }
145
+
146
+ private saveSession(namespaces: Namespaces): void {
147
+ const storage = this.getStorage();
148
+ storage.setItem<CoinbaseSession>(SESSION_KEY, { namespaces });
149
+ }
150
+
151
+ override async restoreSession(): Promise<boolean> {
152
+ const storage = this.getStorage();
153
+ const session = await storage.getItem<CoinbaseSession>(SESSION_KEY);
154
+ if (!session) {
155
+ return false;
156
+ }
157
+
158
+ const { namespaces } = session;
159
+ this.namespaces = namespaces;
160
+
161
+ return true;
162
+ }
163
+
164
+ private getStorage(): Storage {
165
+ if (!this.storage) {
166
+ throw new Error('CoinbaseConnector: Storage not initialized');
167
+ }
168
+
169
+ return this.storage;
170
+ }
171
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { CoinbaseConnector } from './connectors/CoinbaseConnector';
2
+ export type { CoinbaseConnectorConfig } from './types';
@@ -0,0 +1,106 @@
1
+ import EventEmitter from 'events';
2
+ import {
3
+ type Provider,
4
+ type RequestArguments,
5
+ StringUtil
6
+ } from '@reown/appkit-common-react-native';
7
+ import { configure, WalletMobileSDKEVMProvider } from '@coinbase/wallet-mobile-sdk';
8
+ import type { CoinbaseProviderConfig } from '../types';
9
+
10
+ export class CoinbaseProvider extends EventEmitter implements Provider {
11
+ private readonly config: CoinbaseProviderConfig;
12
+ private provider: WalletMobileSDKEVMProvider;
13
+ private chainChangedListeners = new Map<
14
+ (args?: any) => void,
15
+ (hexChainId: `0x${string}`) => void
16
+ >();
17
+
18
+ constructor(config: CoinbaseProviderConfig) {
19
+ super();
20
+ this.config = config;
21
+ configure({
22
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
23
+ callbackURL: new URL(this.config.redirect), // App Universal Link
24
+ hostPackageName: 'org.toshi'
25
+ });
26
+ this.provider = new WalletMobileSDKEVMProvider({
27
+ ...this.config,
28
+ jsonRpcUrl: this.config.jsonRpcUrl,
29
+ storage: this.config.storage
30
+ });
31
+ }
32
+
33
+ async connect<T = string[]>(): Promise<T> {
34
+ try {
35
+ let accounts: string[] = [];
36
+ const isConnected = this.provider.connected;
37
+
38
+ if (!isConnected) {
39
+ accounts = await this.provider.request({
40
+ method: 'eth_requestAccounts',
41
+ params: []
42
+ });
43
+ } else {
44
+ accounts = this.provider.selectedAddress ? [this.provider.selectedAddress] : [];
45
+ }
46
+
47
+ return accounts as T;
48
+ } catch (error) {
49
+ console.warn('CoinbaseProvider: connect error', error);
50
+
51
+ throw error;
52
+ }
53
+ }
54
+ async disconnect(): Promise<void> {
55
+ this.provider.disconnect();
56
+
57
+ return Promise.resolve();
58
+ }
59
+
60
+ request<T = unknown>(args: RequestArguments): Promise<T> {
61
+ return this.provider.request(args);
62
+ }
63
+
64
+ getChainId(): `0x${string}` {
65
+ return this.provider.chainId as `0x${string}`;
66
+ }
67
+
68
+ onChainChanged(hexChainId: `0x${string}`): void {
69
+ const chainId = StringUtil.hexToString(hexChainId);
70
+ this.emit('chainChanged', { chainId });
71
+ }
72
+
73
+ override on(event: string, listener: (args?: any) => void): any {
74
+ if (event === 'chainChanged') {
75
+ // Create middleware that formats the chain ID before calling the original listener
76
+ const chainChangedMiddleware = (hexChainId: `0x${string}`) => {
77
+ const chainId = StringUtil.hexToString(hexChainId);
78
+ listener(chainId);
79
+ };
80
+
81
+ // Store the mapping between original listener and middleware
82
+ this.chainChangedListeners.set(listener, chainChangedMiddleware);
83
+
84
+ return this.provider.on('chainChanged', chainChangedMiddleware);
85
+ }
86
+
87
+ return this.provider.on(event, listener);
88
+ }
89
+
90
+ override off(event: string, listener: (args?: any) => void): any {
91
+ if (event === 'chainChanged') {
92
+ // Get the middleware wrapper for this listener
93
+ const middleware = this.chainChangedListeners.get(listener);
94
+ if (middleware) {
95
+ // Remove the middleware from the provider
96
+ this.provider.off('chainChanged', middleware);
97
+ // Remove the mapping
98
+ this.chainChangedListeners.delete(listener);
99
+
100
+ return this;
101
+ }
102
+ }
103
+
104
+ return this.provider.off(event, listener);
105
+ }
106
+ }
package/src/types.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { MMKV } from 'react-native-mmkv';
2
+ import type { Namespaces } from '@reown/appkit-common-react-native';
3
+ import type {
4
+ KVStorage,
5
+ WalletMobileSDKProviderOptions
6
+ } from '@coinbase/wallet-mobile-sdk/build/WalletMobileSDKEVMProvider';
7
+ import type { COINBASE_METHODS } from './utils';
8
+
9
+ export type CoinbaseProviderConfig = Omit<WalletMobileSDKProviderOptions, 'chainId' | 'address'> & {
10
+ redirect: string;
11
+ };
12
+
13
+ export type Values<T> = T[keyof T];
14
+
15
+ export type CoinbaseMethod = Values<typeof COINBASE_METHODS>;
16
+
17
+ export type CoinbaseSession = {
18
+ namespaces: Namespaces;
19
+ };
20
+
21
+ export type CoinbaseConnectorConfig = {
22
+ storage?: KVStorage | MMKV;
23
+ jsonRpcUrl?: string;
24
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,48 @@
1
+ import type {
2
+ CaipAddress,
3
+ Namespaces,
4
+ ProposalNamespaces
5
+ } from '@reown/appkit-common-react-native';
6
+
7
+ export const COINBASE_METHODS = {
8
+ REQUEST_ACCOUNTS: 'eth_requestAccounts',
9
+ SIGN_TRANSACTION: 'eth_signTransaction',
10
+ SEND_TRANSACTION: 'eth_sendTransaction',
11
+ SIGN_MESSAGE: 'personal_sign',
12
+ SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
13
+ SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
14
+ SWITCH_CHAIN: 'wallet_switchEthereumChain',
15
+ ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
16
+ WATCH_ASSET: 'wallet_watchAsset'
17
+ } as const;
18
+
19
+ export function getCoinbaseNamespace(
20
+ namespaces?: ProposalNamespaces,
21
+ accounts?: string[]
22
+ ): Namespaces {
23
+ if (!namespaces || !accounts) {
24
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
25
+ }
26
+
27
+ const namespace = namespaces['eip155'];
28
+
29
+ if (!namespace) {
30
+ throw new Error('CoinbaseConnector: Namespace not found');
31
+ }
32
+
33
+ let caipAddresses: CaipAddress[] = [];
34
+
35
+ for (const account of accounts) {
36
+ namespace.chains?.forEach(chain => {
37
+ caipAddresses.push(`${chain}:${account}`);
38
+ });
39
+ }
40
+
41
+ return {
42
+ ['eip155']: {
43
+ ...namespace,
44
+ methods: Object.values(COINBASE_METHODS),
45
+ accounts: caipAddresses
46
+ }
47
+ };
48
+ }