@reown/appkit-coinbase-react-native 0.0.0-feat-coinbase-20250722173213

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 (36) hide show
  1. package/lib/commonjs/connectors/CoinbaseConnector.js +133 -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/providers/CoinbaseProvider.js +70 -0
  6. package/lib/commonjs/providers/CoinbaseProvider.js.map +1 -0
  7. package/lib/commonjs/types.js +6 -0
  8. package/lib/commonjs/types.js.map +1 -0
  9. package/lib/commonjs/utils.js +59 -0
  10. package/lib/commonjs/utils.js.map +1 -0
  11. package/lib/module/connectors/CoinbaseConnector.js +126 -0
  12. package/lib/module/connectors/CoinbaseConnector.js.map +1 -0
  13. package/lib/module/index.js +2 -0
  14. package/lib/module/index.js.map +1 -0
  15. package/lib/module/providers/CoinbaseProvider.js +62 -0
  16. package/lib/module/providers/CoinbaseProvider.js.map +1 -0
  17. package/lib/module/types.js +2 -0
  18. package/lib/module/types.js.map +1 -0
  19. package/lib/module/utils.js +49 -0
  20. package/lib/module/utils.js.map +1 -0
  21. package/lib/typescript/connectors/CoinbaseConnector.d.ts +22 -0
  22. package/lib/typescript/connectors/CoinbaseConnector.d.ts.map +1 -0
  23. package/lib/typescript/index.d.ts +3 -0
  24. package/lib/typescript/index.d.ts.map +1 -0
  25. package/lib/typescript/providers/CoinbaseProvider.d.ts +16 -0
  26. package/lib/typescript/providers/CoinbaseProvider.d.ts.map +1 -0
  27. package/lib/typescript/types.d.ts +17 -0
  28. package/lib/typescript/types.d.ts.map +1 -0
  29. package/lib/typescript/utils.d.ts +18 -0
  30. package/lib/typescript/utils.d.ts.map +1 -0
  31. package/package.json +62 -0
  32. package/src/connectors/CoinbaseConnector.ts +160 -0
  33. package/src/index.ts +2 -0
  34. package/src/providers/CoinbaseProvider.ts +75 -0
  35. package/src/types.ts +27 -0
  36. package/src/utils.ts +68 -0
@@ -0,0 +1,133 @@
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
+ if (!ops.metadata.redirect?.universal) {
22
+ throw new Error('CoinbaseConnector: Universal link not found in metadata');
23
+ }
24
+ this.provider = new _CoinbaseProvider.CoinbaseProvider({
25
+ redirect: ops.metadata.redirect.universal,
26
+ // use config storage only, as it needs to be mmkv-compatible
27
+ storage: this.config.storage
28
+ });
29
+ await this.restoreSession();
30
+ }
31
+ async connect(opts) {
32
+ const accounts = await this.getProvider().connect();
33
+ const namespaces = (0, _utils.getCoinbaseNamespace)(opts?.namespaces, accounts);
34
+ this.namespaces = namespaces;
35
+ this.saveSession(namespaces);
36
+ return this.namespaces;
37
+ }
38
+ async disconnect() {
39
+ await super.disconnect();
40
+ this.deleteSession();
41
+ }
42
+ getProvider() {
43
+ if (!this.provider) {
44
+ throw new Error('CoinbaseConnector: Provider not initialized');
45
+ }
46
+ return this.provider;
47
+ }
48
+ getNamespaces() {
49
+ if (!this.namespaces) {
50
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
51
+ }
52
+ return this.namespaces;
53
+ }
54
+ getChainId() {
55
+ const hexChainId = this.getProvider().getChainId();
56
+ const chainId = (0, _utils.hexToString)(hexChainId);
57
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}`;
58
+ }
59
+ getWalletInfo() {
60
+ // TODO: Add icon
61
+ return {
62
+ name: 'Coinbase Wallet',
63
+ description: 'Your home to everything onchain',
64
+ url: 'https://www.coinbase.com/wallet'
65
+ };
66
+ }
67
+ getProperties() {
68
+ return undefined;
69
+ }
70
+ async switchNetwork(network) {
71
+ const provider = this.getProvider();
72
+ const chainId_ = (0, _utils.numberToHex)(network.id);
73
+ try {
74
+ await provider.request({
75
+ method: 'wallet_switchEthereumChain',
76
+ params: [{
77
+ chainId: chainId_
78
+ }]
79
+ });
80
+ } catch (error) {
81
+ // Indicates chain is not added to provider
82
+ if (error?.code === 4902) {
83
+ try {
84
+ await provider.request({
85
+ method: 'wallet_addEthereumChain',
86
+ params: [{
87
+ chainId: chainId_,
88
+ chainName: network.name,
89
+ nativeCurrency: network.nativeCurrency,
90
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
91
+ blockExplorerUrls: [network.blockExplorers?.default.url]
92
+ }]
93
+ });
94
+ } catch (e) {
95
+ console.warn('CoinbaseConnector: switchNetwork error', e);
96
+ throw e;
97
+ }
98
+ }
99
+ console.warn('CoinbaseConnector: switchNetwork error', error);
100
+ throw error;
101
+ }
102
+ }
103
+ deleteSession() {
104
+ const storage = this.getStorage();
105
+ storage.removeItem(SESSION_KEY);
106
+ }
107
+ saveSession(namespaces) {
108
+ const storage = this.getStorage();
109
+ storage.setItem(SESSION_KEY, JSON.stringify({
110
+ namespaces
111
+ }));
112
+ }
113
+ async restoreSession() {
114
+ const storage = this.getStorage();
115
+ const session = await storage.getItem(SESSION_KEY);
116
+ if (!session) {
117
+ return false;
118
+ }
119
+ const {
120
+ namespaces
121
+ } = JSON.parse(session);
122
+ this.namespaces = namespaces;
123
+ return true;
124
+ }
125
+ getStorage() {
126
+ if (!this.storage) {
127
+ throw new Error('CoinbaseConnector: Storage not initialized');
128
+ }
129
+ return this.storage;
130
+ }
131
+ }
132
+ exports.CoinbaseConnector = CoinbaseConnector;
133
+ //# 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","metadata","redirect","universal","Error","provider","CoinbaseProvider","storage","restoreSession","connect","opts","accounts","getProvider","namespaces","getCoinbaseNamespace","saveSession","disconnect","deleteSession","getNamespaces","getChainId","hexChainId","chainId","hexToString","getWalletInfo","name","description","url","getProperties","undefined","switchNetwork","network","chainId_","numberToHex","id","request","method","params","error","code","chainName","nativeCurrency","rpcUrls","default","http","blockExplorerUrls","blockExplorers","e","console","warn","getStorage","removeItem","setItem","JSON","stringify","session","getItem","parse","exports"],"sourceRoot":"../../../src","sources":["connectors/CoinbaseConnector.ts"],"mappings":"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"}
@@ -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"}
@@ -0,0 +1,70 @@
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 _walletMobileSdk = require("@coinbase/wallet-mobile-sdk");
9
+ var _utils = require("../utils");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ class CoinbaseProvider extends _events.default {
12
+ constructor(config) {
13
+ super();
14
+ this.config = config;
15
+ (0, _walletMobileSdk.configure)({
16
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
17
+ callbackURL: new URL(this.config.redirect),
18
+ // App Universal Link
19
+ hostPackageName: 'org.toshi'
20
+ });
21
+ this.provider = new _walletMobileSdk.WalletMobileSDKEVMProvider({
22
+ ...this.config,
23
+ jsonRpcUrl: this.config.rpcUrl,
24
+ chainId: this.config.defaultChain,
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
+
41
+ //TODO: check switch chain
42
+
43
+ return accounts;
44
+ } catch (error) {
45
+ console.warn('CoinbaseProvider: connect error', error);
46
+ throw error;
47
+ }
48
+ }
49
+ async disconnect() {
50
+ this.provider.disconnect();
51
+ return Promise.resolve();
52
+ }
53
+ request(args) {
54
+ if (!(0, _utils.isValidMethod)(args.method)) {
55
+ throw new Error(`CoinbaseProvider: Invalid method: ${args.method}`);
56
+ }
57
+ return this.provider.request(args);
58
+ }
59
+ getChainId() {
60
+ return this.provider.chainId;
61
+ }
62
+ on(event, listener) {
63
+ return this.provider.on(event, listener);
64
+ }
65
+ off(event, listener) {
66
+ return this.provider.off(event, listener);
67
+ }
68
+ }
69
+ exports.CoinbaseProvider = CoinbaseProvider;
70
+ //# sourceMappingURL=CoinbaseProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_events","_interopRequireDefault","require","_walletMobileSdk","_utils","e","__esModule","default","CoinbaseProvider","EventEmitter","constructor","config","configure","hostURL","URL","callbackURL","redirect","hostPackageName","provider","WalletMobileSDKEVMProvider","jsonRpcUrl","rpcUrl","chainId","defaultChain","storage","connect","accounts","isConnected","connected","request","method","params","selectedAddress","error","console","warn","disconnect","Promise","resolve","args","isValidMethod","Error","getChainId","on","event","listener","off","exports"],"sourceRoot":"../../../src","sources":["providers/CoinbaseProvider.ts"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,sBAAA,CAAAC,OAAA;AAEA,IAAAC,gBAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AAAyC,SAAAD,uBAAAI,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAGlC,MAAMG,gBAAgB,SAASC,eAAY,CAAqB;EAIrEC,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,CAACU,MAAM;MAC9BC,OAAO,EAAE,IAAI,CAACX,MAAM,CAACY,YAAY;MACjCC,OAAO,EAAE,IAAI,CAACb,MAAM,CAACa;IACvB,CAAC,CAAC;EACJ;EAEA,MAAMC,OAAOA,CAAA,EAA6B;IACxC,IAAI;MACF,IAAIC,QAAkB,GAAG,EAAE;MAC3B,MAAMC,WAAW,GAAG,IAAI,CAACT,QAAQ,CAACU,SAAS;MAE3C,IAAI,CAACD,WAAW,EAAE;QAChBD,QAAQ,GAAG,MAAM,IAAI,CAACR,QAAQ,CAACW,OAAO,CAAC;UACrCC,MAAM,EAAE,qBAAqB;UAC7BC,MAAM,EAAE;QACV,CAAC,CAAC;MACJ,CAAC,MAAM;QACLL,QAAQ,GAAG,IAAI,CAACR,QAAQ,CAACc,eAAe,GAAG,CAAC,IAAI,CAACd,QAAQ,CAACc,eAAe,CAAC,GAAG,EAAE;MACjF;;MAEA;;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,CAAClB,QAAQ,CAACkB,UAAU,CAAC,CAAC;IAE1B,OAAOC,OAAO,CAACC,OAAO,CAAC,CAAC;EAC1B;EAEAT,OAAOA,CAAcU,IAAsB,EAAc;IACvD,IAAI,CAAC,IAAAC,oBAAa,EAACD,IAAI,CAACT,MAAM,CAAC,EAAE;MAC/B,MAAM,IAAIW,KAAK,CAAE,qCAAoCF,IAAI,CAACT,MAAO,EAAC,CAAC;IACrE;IAEA,OAAO,IAAI,CAACZ,QAAQ,CAACW,OAAO,CAACU,IAAI,CAAC;EACpC;EAEAG,UAAUA,CAAA,EAAkB;IAC1B,OAAO,IAAI,CAACxB,QAAQ,CAACI,OAAO;EAC9B;EAESqB,EAAEA,CAACC,KAAa,EAAEC,QAA8B,EAAO;IAC9D,OAAO,IAAI,CAAC3B,QAAQ,CAACyB,EAAE,CAACC,KAAK,EAAEC,QAAQ,CAAC;EAC1C;EAESC,GAAGA,CAACF,KAAa,EAAEC,QAA8B,EAAO;IAC/D,OAAO,IAAI,CAAC3B,QAAQ,CAAC4B,GAAG,CAACF,KAAK,EAAEC,QAAQ,CAAC;EAC3C;AACF;AAACE,OAAA,CAAAvC,gBAAA,GAAAA,gBAAA"}
@@ -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":""}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.COINBASE_METHODS = void 0;
7
+ exports.getCoinbaseNamespace = getCoinbaseNamespace;
8
+ exports.hexToString = hexToString;
9
+ exports.isValidMethod = isValidMethod;
10
+ exports.numberToHex = numberToHex;
11
+ const COINBASE_METHODS = exports.COINBASE_METHODS = {
12
+ REQUEST_ACCOUNTS: 'eth_requestAccounts',
13
+ SIGN_TRANSACTION: 'eth_signTransaction',
14
+ SEND_TRANSACTION: 'eth_sendTransaction',
15
+ SIGN_MESSAGE: 'personal_sign',
16
+ SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
17
+ SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
18
+ SWITCH_CHAIN: 'wallet_switchEthereumChain',
19
+ ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
20
+ WATCH_ASSET: 'wallet_watchAsset'
21
+ };
22
+ function isValidMethod(method) {
23
+ return Object.values(COINBASE_METHODS).includes(method);
24
+ }
25
+ function getCoinbaseNamespace(namespaces, accounts) {
26
+ if (!namespaces || !accounts) {
27
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
28
+ }
29
+ const namespace = namespaces['eip155'];
30
+ if (!namespace) {
31
+ throw new Error('CoinbaseConnector: Namespace not found');
32
+ }
33
+ let caipAddresses = [];
34
+ for (const account of accounts) {
35
+ namespace.chains?.forEach(chain => {
36
+ caipAddresses.push(`${chain}:${account}`);
37
+ });
38
+ }
39
+ return {
40
+ ['eip155']: {
41
+ ...namespace,
42
+ methods: Object.values(COINBASE_METHODS),
43
+ accounts: caipAddresses
44
+ }
45
+ };
46
+ }
47
+ function numberToHex(value) {
48
+ // Convert string to number first, then to hex
49
+ const num = typeof value === 'string' ? parseInt(value, 10) : value;
50
+ return `0x${num.toString(16)}`;
51
+ }
52
+ function hexToString(hexValue) {
53
+ // Remove 0x prefix if present
54
+ const cleanHex = hexValue.startsWith('0x') ? hexValue.slice(2) : hexValue;
55
+ // Convert hex to decimal number, then to string
56
+
57
+ return parseInt(cleanHex, 16).toString();
58
+ }
59
+ //# 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","isValidMethod","method","Object","values","includes","getCoinbaseNamespace","namespaces","accounts","Error","namespace","caipAddresses","account","chains","forEach","chain","push","methods","numberToHex","value","num","parseInt","toString","hexToString","hexValue","cleanHex","startsWith","slice"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":";;;;;;;;;;AAOO,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,aAAaA,CAACC,MAAc,EAA4B;EACtE,OAAOC,MAAM,CAACC,MAAM,CAACd,gBAAgB,CAAC,CAACe,QAAQ,CAACH,MAAwB,CAAC;AAC3E;AAEO,SAASI,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,CAAE,GAAED,KAAM,IAAGH,OAAQ,EAAC,CAAC;IAC3C,CAAC,CAAC;EACJ;EAEA,OAAO;IACL,CAAC,QAAQ,GAAG;MACV,GAAGF,SAAS;MACZO,OAAO,EAAEd,MAAM,CAACC,MAAM,CAACd,gBAAgB,CAAC;MACxCkB,QAAQ,EAAEG;IACZ;EACF,CAAC;AACH;AAEO,SAASO,WAAWA,CAACC,KAAsB,EAAE;EAClD;EACA,MAAMC,GAAG,GAAG,OAAOD,KAAK,KAAK,QAAQ,GAAGE,QAAQ,CAACF,KAAK,EAAE,EAAE,CAAC,GAAGA,KAAK;EAEnE,OAAQ,KAAIC,GAAG,CAACE,QAAQ,CAAC,EAAE,CAAE,EAAC;AAChC;AAEO,SAASC,WAAWA,CAACC,QAAgB,EAAE;EAC5C;EACA,MAAMC,QAAQ,GAAGD,QAAQ,CAACE,UAAU,CAAC,IAAI,CAAC,GAAGF,QAAQ,CAACG,KAAK,CAAC,CAAC,CAAC,GAAGH,QAAQ;EACzE;;EAEA,OAAOH,QAAQ,CAACI,QAAQ,EAAE,EAAE,CAAC,CAACH,QAAQ,CAAC,CAAC;AAC1C"}
@@ -0,0 +1,126 @@
1
+ import { WalletConnector } from '@reown/appkit-common-react-native';
2
+ import { getCoinbaseNamespace, hexToString, numberToHex } from '../utils';
3
+ import { CoinbaseProvider } from '../providers/CoinbaseProvider';
4
+ const SESSION_KEY = '@appkit/coinbase-connector/session';
5
+ export class CoinbaseConnector extends WalletConnector {
6
+ static SUPPORTED_NAMESPACE = 'eip155';
7
+ constructor(config) {
8
+ super({
9
+ type: 'coinbase'
10
+ });
11
+ this.config = config;
12
+ }
13
+ async init(ops) {
14
+ super.init(ops);
15
+ if (!ops.metadata.redirect?.universal) {
16
+ throw new Error('CoinbaseConnector: Universal link not found in metadata');
17
+ }
18
+ this.provider = new CoinbaseProvider({
19
+ redirect: ops.metadata.redirect.universal,
20
+ // use config storage only, as it needs to be mmkv-compatible
21
+ storage: this.config.storage
22
+ });
23
+ await this.restoreSession();
24
+ }
25
+ async connect(opts) {
26
+ const accounts = await this.getProvider().connect();
27
+ const namespaces = getCoinbaseNamespace(opts?.namespaces, accounts);
28
+ this.namespaces = namespaces;
29
+ this.saveSession(namespaces);
30
+ return this.namespaces;
31
+ }
32
+ async disconnect() {
33
+ await super.disconnect();
34
+ this.deleteSession();
35
+ }
36
+ getProvider() {
37
+ if (!this.provider) {
38
+ throw new Error('CoinbaseConnector: Provider not initialized');
39
+ }
40
+ return this.provider;
41
+ }
42
+ getNamespaces() {
43
+ if (!this.namespaces) {
44
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
45
+ }
46
+ return this.namespaces;
47
+ }
48
+ getChainId() {
49
+ const hexChainId = this.getProvider().getChainId();
50
+ const chainId = hexToString(hexChainId);
51
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}`;
52
+ }
53
+ getWalletInfo() {
54
+ // TODO: Add icon
55
+ return {
56
+ name: 'Coinbase Wallet',
57
+ description: 'Your home to everything onchain',
58
+ url: 'https://www.coinbase.com/wallet'
59
+ };
60
+ }
61
+ getProperties() {
62
+ return undefined;
63
+ }
64
+ async switchNetwork(network) {
65
+ const provider = this.getProvider();
66
+ const chainId_ = numberToHex(network.id);
67
+ try {
68
+ await provider.request({
69
+ method: 'wallet_switchEthereumChain',
70
+ params: [{
71
+ chainId: chainId_
72
+ }]
73
+ });
74
+ } catch (error) {
75
+ // Indicates chain is not added to provider
76
+ if (error?.code === 4902) {
77
+ try {
78
+ await provider.request({
79
+ method: 'wallet_addEthereumChain',
80
+ params: [{
81
+ chainId: chainId_,
82
+ chainName: network.name,
83
+ nativeCurrency: network.nativeCurrency,
84
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
85
+ blockExplorerUrls: [network.blockExplorers?.default.url]
86
+ }]
87
+ });
88
+ } catch (e) {
89
+ console.warn('CoinbaseConnector: switchNetwork error', e);
90
+ throw e;
91
+ }
92
+ }
93
+ console.warn('CoinbaseConnector: switchNetwork error', error);
94
+ throw error;
95
+ }
96
+ }
97
+ deleteSession() {
98
+ const storage = this.getStorage();
99
+ storage.removeItem(SESSION_KEY);
100
+ }
101
+ saveSession(namespaces) {
102
+ const storage = this.getStorage();
103
+ storage.setItem(SESSION_KEY, JSON.stringify({
104
+ namespaces
105
+ }));
106
+ }
107
+ async restoreSession() {
108
+ const storage = this.getStorage();
109
+ const session = await storage.getItem(SESSION_KEY);
110
+ if (!session) {
111
+ return false;
112
+ }
113
+ const {
114
+ namespaces
115
+ } = JSON.parse(session);
116
+ this.namespaces = namespaces;
117
+ return true;
118
+ }
119
+ getStorage() {
120
+ if (!this.storage) {
121
+ throw new Error('CoinbaseConnector: Storage not initialized');
122
+ }
123
+ return this.storage;
124
+ }
125
+ }
126
+ //# sourceMappingURL=CoinbaseConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WalletConnector","getCoinbaseNamespace","hexToString","numberToHex","CoinbaseProvider","SESSION_KEY","CoinbaseConnector","SUPPORTED_NAMESPACE","constructor","config","type","init","ops","metadata","redirect","universal","Error","provider","storage","restoreSession","connect","opts","accounts","getProvider","namespaces","saveSession","disconnect","deleteSession","getNamespaces","getChainId","hexChainId","chainId","getWalletInfo","name","description","url","getProperties","undefined","switchNetwork","network","chainId_","id","request","method","params","error","code","chainName","nativeCurrency","rpcUrls","default","http","blockExplorerUrls","blockExplorers","e","console","warn","getStorage","removeItem","setItem","JSON","stringify","session","getItem","parse"],"sourceRoot":"../../../src","sources":["connectors/CoinbaseConnector.ts"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { CoinbaseConnector } from './connectors/CoinbaseConnector';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["CoinbaseConnector"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,gCAAgC"}
@@ -0,0 +1,62 @@
1
+ import EventEmitter from 'events';
2
+ import { configure, WalletMobileSDKEVMProvider } from '@coinbase/wallet-mobile-sdk';
3
+ import { isValidMethod } from '../utils';
4
+ export class CoinbaseProvider extends EventEmitter {
5
+ constructor(config) {
6
+ super();
7
+ this.config = config;
8
+ configure({
9
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
10
+ callbackURL: new URL(this.config.redirect),
11
+ // App Universal Link
12
+ hostPackageName: 'org.toshi'
13
+ });
14
+ this.provider = new WalletMobileSDKEVMProvider({
15
+ ...this.config,
16
+ jsonRpcUrl: this.config.rpcUrl,
17
+ chainId: this.config.defaultChain,
18
+ storage: this.config.storage
19
+ });
20
+ }
21
+ async connect() {
22
+ try {
23
+ let accounts = [];
24
+ const isConnected = this.provider.connected;
25
+ if (!isConnected) {
26
+ accounts = await this.provider.request({
27
+ method: 'eth_requestAccounts',
28
+ params: []
29
+ });
30
+ } else {
31
+ accounts = this.provider.selectedAddress ? [this.provider.selectedAddress] : [];
32
+ }
33
+
34
+ //TODO: check switch chain
35
+
36
+ return accounts;
37
+ } catch (error) {
38
+ console.warn('CoinbaseProvider: connect error', error);
39
+ throw error;
40
+ }
41
+ }
42
+ async disconnect() {
43
+ this.provider.disconnect();
44
+ return Promise.resolve();
45
+ }
46
+ request(args) {
47
+ if (!isValidMethod(args.method)) {
48
+ throw new Error(`CoinbaseProvider: Invalid method: ${args.method}`);
49
+ }
50
+ return this.provider.request(args);
51
+ }
52
+ getChainId() {
53
+ return this.provider.chainId;
54
+ }
55
+ on(event, listener) {
56
+ return this.provider.on(event, listener);
57
+ }
58
+ off(event, listener) {
59
+ return this.provider.off(event, listener);
60
+ }
61
+ }
62
+ //# sourceMappingURL=CoinbaseProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["EventEmitter","configure","WalletMobileSDKEVMProvider","isValidMethod","CoinbaseProvider","constructor","config","hostURL","URL","callbackURL","redirect","hostPackageName","provider","jsonRpcUrl","rpcUrl","chainId","defaultChain","storage","connect","accounts","isConnected","connected","request","method","params","selectedAddress","error","console","warn","disconnect","Promise","resolve","args","Error","getChainId","on","event","listener","off"],"sourceRoot":"../../../src","sources":["providers/CoinbaseProvider.ts"],"mappings":"AAAA,OAAOA,YAAY,MAAM,QAAQ;AAEjC,SAASC,SAAS,EAAEC,0BAA0B,QAAQ,6BAA6B;AACnF,SAASC,aAAa,QAAQ,UAAU;AAGxC,OAAO,MAAMC,gBAAgB,SAASJ,YAAY,CAAqB;EAIrEK,WAAWA,CAACC,MAA8B,EAAE;IAC1C,KAAK,CAAC,CAAC;IACP,IAAI,CAACA,MAAM,GAAGA,MAAM;IACpBL,SAAS,CAAC;MACRM,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,IAAIV,0BAA0B,CAAC;MAC7C,GAAG,IAAI,CAACI,MAAM;MACdO,UAAU,EAAE,IAAI,CAACP,MAAM,CAACQ,MAAM;MAC9BC,OAAO,EAAE,IAAI,CAACT,MAAM,CAACU,YAAY;MACjCC,OAAO,EAAE,IAAI,CAACX,MAAM,CAACW;IACvB,CAAC,CAAC;EACJ;EAEA,MAAMC,OAAOA,CAAA,EAA6B;IACxC,IAAI;MACF,IAAIC,QAAkB,GAAG,EAAE;MAC3B,MAAMC,WAAW,GAAG,IAAI,CAACR,QAAQ,CAACS,SAAS;MAE3C,IAAI,CAACD,WAAW,EAAE;QAChBD,QAAQ,GAAG,MAAM,IAAI,CAACP,QAAQ,CAACU,OAAO,CAAC;UACrCC,MAAM,EAAE,qBAAqB;UAC7BC,MAAM,EAAE;QACV,CAAC,CAAC;MACJ,CAAC,MAAM;QACLL,QAAQ,GAAG,IAAI,CAACP,QAAQ,CAACa,eAAe,GAAG,CAAC,IAAI,CAACb,QAAQ,CAACa,eAAe,CAAC,GAAG,EAAE;MACjF;;MAEA;;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,CAACjB,QAAQ,CAACiB,UAAU,CAAC,CAAC;IAE1B,OAAOC,OAAO,CAACC,OAAO,CAAC,CAAC;EAC1B;EAEAT,OAAOA,CAAcU,IAAsB,EAAc;IACvD,IAAI,CAAC7B,aAAa,CAAC6B,IAAI,CAACT,MAAM,CAAC,EAAE;MAC/B,MAAM,IAAIU,KAAK,CAAE,qCAAoCD,IAAI,CAACT,MAAO,EAAC,CAAC;IACrE;IAEA,OAAO,IAAI,CAACX,QAAQ,CAACU,OAAO,CAACU,IAAI,CAAC;EACpC;EAEAE,UAAUA,CAAA,EAAkB;IAC1B,OAAO,IAAI,CAACtB,QAAQ,CAACG,OAAO;EAC9B;EAESoB,EAAEA,CAACC,KAAa,EAAEC,QAA8B,EAAO;IAC9D,OAAO,IAAI,CAACzB,QAAQ,CAACuB,EAAE,CAACC,KAAK,EAAEC,QAAQ,CAAC;EAC1C;EAESC,GAAGA,CAACF,KAAa,EAAEC,QAA8B,EAAO;IAC/D,OAAO,IAAI,CAACzB,QAAQ,CAAC0B,GAAG,CAACF,KAAK,EAAEC,QAAQ,CAAC;EAC3C;AACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":""}
@@ -0,0 +1,49 @@
1
+ export const COINBASE_METHODS = {
2
+ REQUEST_ACCOUNTS: 'eth_requestAccounts',
3
+ SIGN_TRANSACTION: 'eth_signTransaction',
4
+ SEND_TRANSACTION: 'eth_sendTransaction',
5
+ SIGN_MESSAGE: 'personal_sign',
6
+ SIGN_TYPED_DATA_V3: 'eth_signTypedData_v3',
7
+ SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
8
+ SWITCH_CHAIN: 'wallet_switchEthereumChain',
9
+ ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
10
+ WATCH_ASSET: 'wallet_watchAsset'
11
+ };
12
+ export function isValidMethod(method) {
13
+ return Object.values(COINBASE_METHODS).includes(method);
14
+ }
15
+ export function getCoinbaseNamespace(namespaces, accounts) {
16
+ if (!namespaces || !accounts) {
17
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
18
+ }
19
+ const namespace = namespaces['eip155'];
20
+ if (!namespace) {
21
+ throw new Error('CoinbaseConnector: Namespace not found');
22
+ }
23
+ let caipAddresses = [];
24
+ for (const account of accounts) {
25
+ namespace.chains?.forEach(chain => {
26
+ caipAddresses.push(`${chain}:${account}`);
27
+ });
28
+ }
29
+ return {
30
+ ['eip155']: {
31
+ ...namespace,
32
+ methods: Object.values(COINBASE_METHODS),
33
+ accounts: caipAddresses
34
+ }
35
+ };
36
+ }
37
+ export function numberToHex(value) {
38
+ // Convert string to number first, then to hex
39
+ const num = typeof value === 'string' ? parseInt(value, 10) : value;
40
+ return `0x${num.toString(16)}`;
41
+ }
42
+ export function hexToString(hexValue) {
43
+ // Remove 0x prefix if present
44
+ const cleanHex = hexValue.startsWith('0x') ? hexValue.slice(2) : hexValue;
45
+ // Convert hex to decimal number, then to string
46
+
47
+ return parseInt(cleanHex, 16).toString();
48
+ }
49
+ //# 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","isValidMethod","method","Object","values","includes","getCoinbaseNamespace","namespaces","accounts","Error","namespace","caipAddresses","account","chains","forEach","chain","push","methods","numberToHex","value","num","parseInt","toString","hexToString","hexValue","cleanHex","startsWith","slice"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":"AAOA,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,aAAaA,CAACC,MAAc,EAA4B;EACtE,OAAOC,MAAM,CAACC,MAAM,CAACb,gBAAgB,CAAC,CAACc,QAAQ,CAACH,MAAwB,CAAC;AAC3E;AAEA,OAAO,SAASI,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,CAAE,GAAED,KAAM,IAAGH,OAAQ,EAAC,CAAC;IAC3C,CAAC,CAAC;EACJ;EAEA,OAAO;IACL,CAAC,QAAQ,GAAG;MACV,GAAGF,SAAS;MACZO,OAAO,EAAEd,MAAM,CAACC,MAAM,CAACb,gBAAgB,CAAC;MACxCiB,QAAQ,EAAEG;IACZ;EACF,CAAC;AACH;AAEA,OAAO,SAASO,WAAWA,CAACC,KAAsB,EAAE;EAClD;EACA,MAAMC,GAAG,GAAG,OAAOD,KAAK,KAAK,QAAQ,GAAGE,QAAQ,CAACF,KAAK,EAAE,EAAE,CAAC,GAAGA,KAAK;EAEnE,OAAQ,KAAIC,GAAG,CAACE,QAAQ,CAAC,EAAE,CAAE,EAAC;AAChC;AAEA,OAAO,SAASC,WAAWA,CAACC,QAAgB,EAAE;EAC5C;EACA,MAAMC,QAAQ,GAAGD,QAAQ,CAACE,UAAU,CAAC,IAAI,CAAC,GAAGF,QAAQ,CAACG,KAAK,CAAC,CAAC,CAAC,GAAGH,QAAQ;EACzE;;EAEA,OAAOH,QAAQ,CAACI,QAAQ,EAAE,EAAE,CAAC,CAACH,QAAQ,CAAC,CAAC;AAC1C"}
@@ -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?: ConnectOptions): 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,EAEhB,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,EAAE,uBAAuB;IAK5B,IAAI,CAAC,GAAG,EAAE,oBAAoB;IAgB9B,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAU/D,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;IASvC,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,16 @@
1
+ /// <reference types="node" />
2
+ import EventEmitter from 'events';
3
+ import type { Provider, 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
+ constructor(config: CoinbaseProviderConfig);
9
+ connect<T = string[]>(): Promise<T>;
10
+ disconnect(): Promise<void>;
11
+ request<T = unknown>(args: RequestArguments): Promise<T>;
12
+ getChainId(): `0x${string}`;
13
+ on(event: string, listener: (args?: any) => void): any;
14
+ off(event: string, listener: (args?: any) => void): any;
15
+ }
16
+ //# 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,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAGpF,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;gBAEjC,MAAM,EAAE,sBAAsB;IAgBpC,OAAO,CAAC,CAAC,GAAG,MAAM,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC;IAuBnC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAQxD,UAAU,IAAI,KAAK,MAAM,EAAE;IAIlB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG;IAItD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG;CAGjE"}
@@ -0,0 +1,17 @@
1
+ import type { Namespaces } from '@reown/appkit-common-react-native';
2
+ import type { KVStorage, WalletMobileSDKProviderOptions } from '@coinbase/wallet-mobile-sdk/build/WalletMobileSDKEVMProvider';
3
+ import type { COINBASE_METHODS } from './utils';
4
+ export type CoinbaseProviderConfig = Omit<WalletMobileSDKProviderOptions, 'chainId' | 'jsonRpcUrl' | 'address'> & {
5
+ defaultChain?: number;
6
+ redirect: string;
7
+ rpcUrl?: string;
8
+ };
9
+ export type Values<T> = T[keyof T];
10
+ export type CoinbaseMethod = Values<typeof COINBASE_METHODS>;
11
+ export type CoinbaseSession = {
12
+ namespaces: Namespaces;
13
+ };
14
+ export type CoinbaseConnectorConfig = {
15
+ storage?: KVStorage;
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,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,CACvC,8BAA8B,EAC9B,SAAS,GAAG,YAAY,GAAG,SAAS,CACrC,GAAG;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,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,CAAC;CACrB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Namespaces, ProposalNamespaces } from '@reown/appkit-common-react-native';
2
+ import type { CoinbaseMethod } from './types';
3
+ export declare const COINBASE_METHODS: {
4
+ readonly REQUEST_ACCOUNTS: "eth_requestAccounts";
5
+ readonly SIGN_TRANSACTION: "eth_signTransaction";
6
+ readonly SEND_TRANSACTION: "eth_sendTransaction";
7
+ readonly SIGN_MESSAGE: "personal_sign";
8
+ readonly SIGN_TYPED_DATA_V3: "eth_signTypedData_v3";
9
+ readonly SIGN_TYPED_DATA_V4: "eth_signTypedData_v4";
10
+ readonly SWITCH_CHAIN: "wallet_switchEthereumChain";
11
+ readonly ADD_ETHEREUM_CHAIN: "wallet_addEthereumChain";
12
+ readonly WATCH_ASSET: "wallet_watchAsset";
13
+ };
14
+ export declare function isValidMethod(method: string): method is CoinbaseMethod;
15
+ export declare function getCoinbaseNamespace(namespaces?: ProposalNamespaces, accounts?: string[]): Namespaces;
16
+ export declare function numberToHex(value: string | number): string;
17
+ export declare function hexToString(hexValue: string): string;
18
+ //# 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;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,eAAO,MAAM,gBAAgB;;;;;;;;;;CAUnB,CAAC;AAEX,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,cAAc,CAEtE;AAED,wBAAgB,oBAAoB,CAClC,UAAU,CAAC,EAAE,kBAAkB,EAC/B,QAAQ,CAAC,EAAE,MAAM,EAAE,GAClB,UAAU,CA0BZ;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,UAKjD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,UAM3C"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@reown/appkit-coinbase-react-native",
3
+ "version": "0.0.0-feat-coinbase-20250722173213",
4
+ "main": "lib/commonjs/index.js",
5
+ "types": "lib/typescript/index.d.ts",
6
+ "module": "lib/module/index.js",
7
+ "source": "src/index.ts",
8
+ "scripts": {
9
+ "build": "bob build",
10
+ "clean": "rm -rf lib",
11
+ "test": "jest --passWithNoTests",
12
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
13
+ },
14
+ "files": [
15
+ "src",
16
+ "lib"
17
+ ],
18
+ "keywords": [
19
+ "web3",
20
+ "crypto",
21
+ "appkit",
22
+ "walletconnect",
23
+ "react-native",
24
+ "coinbase"
25
+ ],
26
+ "repository": "https://github.com/reown-com/appkit-react-native",
27
+ "author": "Reown <support@reown.com> (https://reown.com)",
28
+ "homepage": "https://reown.com/appkit",
29
+ "license": "Apache-2.0",
30
+ "bugs": {
31
+ "url": "https://github.com/reown-com/appkit-react-native/issues"
32
+ },
33
+ "publishConfig": {
34
+ "registry": "https://registry.npmjs.org/",
35
+ "access": "public"
36
+ },
37
+ "dependencies": {
38
+ "@reown/appkit-common-react-native": "0.0.0-feat-coinbase-20250722173213"
39
+ },
40
+ "peerDependencies": {
41
+ "@coinbase/wallet-mobile-sdk": ">=1.1.2"
42
+ },
43
+ "react-native": "src/index.ts",
44
+ "react-native-builder-bob": {
45
+ "source": "src",
46
+ "output": "lib",
47
+ "targets": [
48
+ "commonjs",
49
+ "module",
50
+ [
51
+ "typescript",
52
+ {
53
+ "tsc": "../../node_modules/.bin/tsc"
54
+ }
55
+ ]
56
+ ]
57
+ },
58
+ "eslintIgnore": [
59
+ "node_modules/",
60
+ "lib/"
61
+ ]
62
+ }
@@ -0,0 +1,160 @@
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
+ } from '@reown/appkit-common-react-native';
13
+ import { getCoinbaseNamespace, hexToString, numberToHex } from '../utils';
14
+ import { CoinbaseProvider } from '../providers/CoinbaseProvider';
15
+ import type { CoinbaseConnectorConfig, CoinbaseSession } from '../types';
16
+
17
+ const SESSION_KEY = '@appkit/coinbase-connector/session';
18
+
19
+ export class CoinbaseConnector extends WalletConnector {
20
+ private static readonly SUPPORTED_NAMESPACE: ChainNamespace = 'eip155';
21
+ private config: CoinbaseConnectorConfig;
22
+
23
+ constructor(config: CoinbaseConnectorConfig) {
24
+ super({ type: 'coinbase' });
25
+ this.config = config;
26
+ }
27
+
28
+ override async init(ops: ConnectorInitOptions) {
29
+ super.init(ops);
30
+
31
+ if (!ops.metadata.redirect?.universal) {
32
+ throw new Error('CoinbaseConnector: Universal link not found in metadata');
33
+ }
34
+
35
+ this.provider = new CoinbaseProvider({
36
+ redirect: ops.metadata.redirect.universal,
37
+ // use config storage only, as it needs to be mmkv-compatible
38
+ storage: this.config.storage
39
+ });
40
+
41
+ await this.restoreSession();
42
+ }
43
+
44
+ override async connect(opts?: ConnectOptions): Promise<Namespaces | undefined> {
45
+ const accounts = await this.getProvider().connect();
46
+
47
+ const namespaces = getCoinbaseNamespace(opts?.namespaces, accounts);
48
+ this.namespaces = namespaces;
49
+ this.saveSession(namespaces);
50
+
51
+ return this.namespaces;
52
+ }
53
+
54
+ override async disconnect(): Promise<void> {
55
+ await super.disconnect();
56
+ this.deleteSession();
57
+ }
58
+
59
+ override getProvider(): CoinbaseProvider {
60
+ if (!this.provider) {
61
+ throw new Error('CoinbaseConnector: Provider not initialized');
62
+ }
63
+
64
+ return this.provider as CoinbaseProvider;
65
+ }
66
+
67
+ override getNamespaces(): Namespaces {
68
+ if (!this.namespaces) {
69
+ throw new Error('CoinbaseConnector: Namespaces not initialized');
70
+ }
71
+
72
+ return this.namespaces;
73
+ }
74
+
75
+ override getChainId(): CaipNetworkId | undefined {
76
+ const hexChainId = this.getProvider().getChainId();
77
+ const chainId = hexToString(hexChainId);
78
+
79
+ return `${CoinbaseConnector.SUPPORTED_NAMESPACE}:${chainId}` as CaipNetworkId;
80
+ }
81
+
82
+ override getWalletInfo(): WalletInfo | undefined {
83
+ // TODO: Add icon
84
+ return {
85
+ name: 'Coinbase Wallet',
86
+ description: 'Your home to everything onchain',
87
+ url: 'https://www.coinbase.com/wallet'
88
+ };
89
+ }
90
+
91
+ override getProperties(): ConnectionProperties | undefined {
92
+ return undefined;
93
+ }
94
+
95
+ override async switchNetwork(network: AppKitNetwork): Promise<void> {
96
+ const provider = this.getProvider();
97
+ const chainId_ = numberToHex(network.id);
98
+
99
+ try {
100
+ await provider.request({
101
+ method: 'wallet_switchEthereumChain',
102
+ params: [{ chainId: chainId_ }]
103
+ });
104
+ } catch (error: any) {
105
+ // Indicates chain is not added to provider
106
+ if (error?.code === 4902) {
107
+ try {
108
+ await provider.request({
109
+ method: 'wallet_addEthereumChain',
110
+ params: [
111
+ {
112
+ chainId: chainId_,
113
+ chainName: network.name,
114
+ nativeCurrency: network.nativeCurrency,
115
+ rpcUrls: [network.rpcUrls.default?.http[0] ?? ''],
116
+ blockExplorerUrls: [network.blockExplorers?.default.url]
117
+ }
118
+ ]
119
+ });
120
+ } catch (e) {
121
+ console.warn('CoinbaseConnector: switchNetwork error', e);
122
+ throw e;
123
+ }
124
+ }
125
+ console.warn('CoinbaseConnector: switchNetwork error', error);
126
+ throw error;
127
+ }
128
+ }
129
+
130
+ private deleteSession(): void {
131
+ const storage = this.getStorage();
132
+ storage.removeItem(SESSION_KEY);
133
+ }
134
+
135
+ private saveSession(namespaces: Namespaces): void {
136
+ const storage = this.getStorage();
137
+ storage.setItem(SESSION_KEY, JSON.stringify({ namespaces }));
138
+ }
139
+
140
+ override async restoreSession(): Promise<boolean> {
141
+ const storage = this.getStorage();
142
+ const session = await storage.getItem<string>(SESSION_KEY);
143
+ if (!session) {
144
+ return false;
145
+ }
146
+
147
+ const { namespaces } = JSON.parse(session) as CoinbaseSession;
148
+ this.namespaces = namespaces;
149
+
150
+ return true;
151
+ }
152
+
153
+ private getStorage(): Storage {
154
+ if (!this.storage) {
155
+ throw new Error('CoinbaseConnector: Storage not initialized');
156
+ }
157
+
158
+ return this.storage;
159
+ }
160
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { CoinbaseConnector } from './connectors/CoinbaseConnector';
2
+ export type { CoinbaseConnectorConfig } from './types';
@@ -0,0 +1,75 @@
1
+ import EventEmitter from 'events';
2
+ import type { Provider, RequestArguments } from '@reown/appkit-common-react-native';
3
+ import { configure, WalletMobileSDKEVMProvider } from '@coinbase/wallet-mobile-sdk';
4
+ import { isValidMethod } from '../utils';
5
+ import type { CoinbaseProviderConfig } from '../types';
6
+
7
+ export class CoinbaseProvider extends EventEmitter implements Provider {
8
+ private readonly config: CoinbaseProviderConfig;
9
+ private provider: WalletMobileSDKEVMProvider;
10
+
11
+ constructor(config: CoinbaseProviderConfig) {
12
+ super();
13
+ this.config = config;
14
+ configure({
15
+ hostURL: new URL('https://wallet.coinbase.com/wsegue'),
16
+ callbackURL: new URL(this.config.redirect), // App Universal Link
17
+ hostPackageName: 'org.toshi'
18
+ });
19
+ this.provider = new WalletMobileSDKEVMProvider({
20
+ ...this.config,
21
+ jsonRpcUrl: this.config.rpcUrl,
22
+ chainId: this.config.defaultChain,
23
+ storage: this.config.storage
24
+ });
25
+ }
26
+
27
+ async connect<T = string[]>(): Promise<T> {
28
+ try {
29
+ let accounts: string[] = [];
30
+ const isConnected = this.provider.connected;
31
+
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
+
41
+ //TODO: check switch chain
42
+
43
+ return accounts as T;
44
+ } catch (error) {
45
+ console.warn('CoinbaseProvider: connect error', error);
46
+
47
+ throw error;
48
+ }
49
+ }
50
+ async disconnect(): Promise<void> {
51
+ this.provider.disconnect();
52
+
53
+ return Promise.resolve();
54
+ }
55
+
56
+ request<T = unknown>(args: RequestArguments): Promise<T> {
57
+ if (!isValidMethod(args.method)) {
58
+ throw new Error(`CoinbaseProvider: Invalid method: ${args.method}`);
59
+ }
60
+
61
+ return this.provider.request(args);
62
+ }
63
+
64
+ getChainId(): `0x${string}` {
65
+ return this.provider.chainId as `0x${string}`;
66
+ }
67
+
68
+ override on(event: string, listener: (args?: any) => void): any {
69
+ return this.provider.on(event, listener);
70
+ }
71
+
72
+ override off(event: string, listener: (args?: any) => void): any {
73
+ return this.provider.off(event, listener);
74
+ }
75
+ }
package/src/types.ts ADDED
@@ -0,0 +1,27 @@
1
+ import type { Namespaces } from '@reown/appkit-common-react-native';
2
+ import type {
3
+ KVStorage,
4
+ WalletMobileSDKProviderOptions
5
+ } from '@coinbase/wallet-mobile-sdk/build/WalletMobileSDKEVMProvider';
6
+ import type { COINBASE_METHODS } from './utils';
7
+
8
+ export type CoinbaseProviderConfig = Omit<
9
+ WalletMobileSDKProviderOptions,
10
+ 'chainId' | 'jsonRpcUrl' | 'address'
11
+ > & {
12
+ defaultChain?: number;
13
+ redirect: string;
14
+ rpcUrl?: string;
15
+ };
16
+
17
+ export type Values<T> = T[keyof T];
18
+
19
+ export type CoinbaseMethod = Values<typeof COINBASE_METHODS>;
20
+
21
+ export type CoinbaseSession = {
22
+ namespaces: Namespaces;
23
+ };
24
+
25
+ export type CoinbaseConnectorConfig = {
26
+ storage?: KVStorage;
27
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,68 @@
1
+ import type {
2
+ CaipAddress,
3
+ Namespaces,
4
+ ProposalNamespaces
5
+ } from '@reown/appkit-common-react-native';
6
+ import type { CoinbaseMethod } from './types';
7
+
8
+ export const 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
+ } as const;
19
+
20
+ export function isValidMethod(method: string): method is CoinbaseMethod {
21
+ return Object.values(COINBASE_METHODS).includes(method as CoinbaseMethod);
22
+ }
23
+
24
+ export function getCoinbaseNamespace(
25
+ namespaces?: ProposalNamespaces,
26
+ accounts?: string[]
27
+ ): Namespaces {
28
+ if (!namespaces || !accounts) {
29
+ throw new Error('CoinbaseConnector: Namespaces or accounts not found');
30
+ }
31
+
32
+ const namespace = namespaces['eip155'];
33
+
34
+ if (!namespace) {
35
+ throw new Error('CoinbaseConnector: Namespace not found');
36
+ }
37
+
38
+ let caipAddresses: CaipAddress[] = [];
39
+
40
+ for (const account of accounts) {
41
+ namespace.chains?.forEach(chain => {
42
+ caipAddresses.push(`${chain}:${account}`);
43
+ });
44
+ }
45
+
46
+ return {
47
+ ['eip155']: {
48
+ ...namespace,
49
+ methods: Object.values(COINBASE_METHODS),
50
+ accounts: caipAddresses
51
+ }
52
+ };
53
+ }
54
+
55
+ export function numberToHex(value: string | number) {
56
+ // Convert string to number first, then to hex
57
+ const num = typeof value === 'string' ? parseInt(value, 10) : value;
58
+
59
+ return `0x${num.toString(16)}`;
60
+ }
61
+
62
+ export function hexToString(hexValue: string) {
63
+ // Remove 0x prefix if present
64
+ const cleanHex = hexValue.startsWith('0x') ? hexValue.slice(2) : hexValue;
65
+ // Convert hex to decimal number, then to string
66
+
67
+ return parseInt(cleanHex, 16).toString();
68
+ }