@rango-dev/provider-xverse 0.0.2-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
File without changes
@@ -0,0 +1,12 @@
1
+ import type { XVerseEvent } from '../types.js';
2
+ import { ActionBuilder } from '@rango-dev/wallets-core';
3
+ import { ChangeAccountSubscriberBuilder } from '@rango-dev/wallets-core/namespaces/common';
4
+ import { type ProviderAPI, type UtxoActions } from '@rango-dev/wallets-core/namespaces/utxo';
5
+ export declare const changeAccountSubscriber: (getInstance: () => ProviderAPI) => ChangeAccountSubscriberBuilder<XVerseEvent, ProviderAPI>;
6
+ declare function canEagerConnect(getInstance: () => ProviderAPI): ActionBuilder<UtxoActions, "canEagerConnect">;
7
+ export declare const utxoBuilders: {
8
+ changeAccountSubscriber: (getInstance: () => ProviderAPI) => ChangeAccountSubscriberBuilder<XVerseEvent, ProviderAPI>;
9
+ canEagerConnect: typeof canEagerConnect;
10
+ };
11
+ export {};
12
+ //# sourceMappingURL=utxo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.d.ts","sourceRoot":"","sources":["../../src/builders/utxo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAC;AAC3F,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,WAAW,EACjB,MAAM,yCAAyC,CAAC;AAIjD,eAAO,MAAM,uBAAuB,gBAAiB,MAAM,WAAW,6DAwBhE,CAAC;AAEP,iBAAS,eAAe,CAAC,WAAW,EAAE,MAAM,WAAW,iDAiBtD;AAED,eAAO,MAAM,YAAY;2CA7C4B,MAAM,WAAW;;CA6CE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type ProviderMetadata } from '@rango-dev/wallets-core';
2
+ export declare const XVERSE_INJECTION_DELAY_MS = 1000;
3
+ export declare const XVERSE_ACCESS_DENIED_ERROR_CODE = -32002;
4
+ export declare const WALLET_ID = "xverse";
5
+ export declare const metadata: ProviderMetadata;
6
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C,eAAO,MAAM,+BAA+B,SAAS,CAAC;AACtD,eAAO,MAAM,SAAS,WAAW,CAAC;AAElC,eAAO,MAAM,QAAQ,EAAE,gBAgCtB,CAAC"}
package/dist/mod.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ declare const versions: () => import("@rango-dev/wallets-core/utils").VersionedProviders;
2
+ export { versions };
3
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,QAAQ,kEAC8C,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,CAAC"}
package/dist/mod.js ADDED
@@ -0,0 +1,2 @@
1
+ var A=Object.defineProperty;var t=(r,e)=>A(r,"name",{value:e,configurable:!0});import{defineVersions as Y}from"@rango-dev/wallets-core/utils";import{ProviderBuilder as J}from"@rango-dev/wallets-core";import"@rango-dev/wallets-core";import{Networks as R}from"@rango-dev/wallets-shared";import{LegacyNetworks as I}from"@rango-dev/wallets-core/legacy";import{getNetworkInstance as C}from"@rango-dev/wallets-shared";import{DefaultSignerFactory as B,TransactionType as _}from"rango-types";import{Networks as T}from"@rango-dev/wallets-shared";import{SignerError as S}from"rango-types";var i=class{static{t(this,"BTCSigner")}provider;constructor(e){this.provider=e}async signMessage(){throw S.UnimplementedError("signMessage")}async signAndSendTx(e){let{asset:o,psbt:n}=e;if(!n)throw new Error("No PSBT found to sign. Ensure a valid PSBT is provided.");if(o.blockchain!==T.BTC)throw new Error(`Signing ${o.blockchain} transaction is not implemented by the signer.`);let u={};n.inputsToSign.forEach(({address:b,signingIndexes:x})=>{u[b]=x});let s=await this.provider.request("signPsbt",{psbt:n.unsignedPsbtBase64,signInputs:u,broadcast:!0});if(s?.error)throw new Error(s.error.message||"Error during transaction sign");if(!s?.result?.txid)throw new Error("Transaction not found!");return{hash:s.result.txid}}};async function d(r){let e=C(r,I.BTC),o=new B;return o.registerSigner(_.TRANSFER,new i(e)),o}t(d,"getSigners");import{LegacyNetworks as l}from"@rango-dev/wallets-core/legacy";function a(){let{XverseProviders:r}=window;if(!r)return null;let e=new Map;return r.BitcoinProvider&&e.set(l.BTC,r.BitcoinProvider),e}t(a,"xverse");function f(){let r=a();if(!r)throw new Error("Xverse is not injected. Please check your wallet.");return r}t(f,"getInstanceOrThrow");function c(){let e=a()?.get(l.BTC);if(!e)throw new Error("Xverse not injected. Please check your wallet.");return e}t(c,"bitcoinXverse");async function g(){let e=await c().request("wallet_connect",{addresses:["payment"],network:"Mainnet"});if(e.error?.message)throw new Error(e.error.message);return e}t(g,"getBitcoinAccounts");var v=1e3,w=-32002,p="xverse",h={name:"xverse",icon:"https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/xverse/icon.svg",extensions:{chrome:"https://chromewebstore.google.com/detail/idnnbdplmphpflfnlkomgpfbpcgelopg",homepage:"https://www.xverse.app/"},properties:[{name:"namespaces",value:{selection:"single",data:[{label:"BTC",value:"UTXO",id:"BTC",getSupportedChains:r=>r.filter(e=>e.name===R.BTC)}]}},{name:"signers",value:{getSigners:async()=>d(f())}}]};import{NamespaceBuilder as M}from"@rango-dev/wallets-core";import{builders as O,standardizeAndThrowError as V}from"@rango-dev/wallets-core/namespaces/common";import{utils as U}from"@rango-dev/wallets-core/namespaces/utxo";import{builders as j}from"@rango-dev/wallets-core/namespaces/utxo";import{ActionBuilder as k}from"@rango-dev/wallets-core";import{ChangeAccountSubscriberBuilder as N}from"@rango-dev/wallets-core/namespaces/common";import{utils as X}from"@rango-dev/wallets-core/namespaces/utxo";var D=t(r=>new N().getInstance(r).onSwitchAccount(e=>{e.payload?.addresses?.length||e.preventDefault()}).format(async(e,o)=>X.formatAccountsToCAIP(o.addresses.filter(n=>n.purpose==="payment").map(n=>n.address))).addEventListener((e,o)=>e.addListener("accountChange",o)).removeEventListener((e,o)=>{}),"changeAccountSubscriber");function L(r){return new k("canEagerConnect").action(async()=>{let e=r();try{let o=await e.request("getAddresses",{purposes:["payment"]});return o.error?.code===w?!1:!!o.result?.addresses?.length}catch{return!1}})}t(L,"canEagerConnect");var m={changeAccountSubscriber:D,canEagerConnect:L};var[q,E]=m.changeAccountSubscriber(c).build(),F=m.canEagerConnect(c).build(),W=j.connect().action(async function(){let r=await g();if(r.result?.addresses?.length===0)throw new Error("Couldn't find any address!");return U.formatAccountsToCAIP(r.result.addresses.map(e=>e.address))}).before(q).or(E).or(V).build(),G=O.disconnect().after(E).build(),P=new M("UTXO",p).action(W).action(G).action(F).build();var y=t(()=>new J(p).init(function(r){let[,e]=r.state();setTimeout(()=>{a()&&(e("installed",!0),console.debug("[xverse] instance detected.",r))},v)}).config("metadata",h).add("utxo",P).build(),"buildProvider");var De=t(()=>Y().version("1.0.0",y()).build(),"versions");export{De as versions};
2
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/mod.ts", "../src/provider.ts", "../src/constants.ts", "../src/signer.ts", "../src/signers/utxoSigner.ts", "../src/utils.ts", "../src/namespaces/utxo.ts", "../src/builders/utxo.ts"],
4
+ "sourcesContent": ["import { defineVersions } from '@rango-dev/wallets-core/utils';\n\nimport { buildProvider } from './provider.js';\n\nconst versions = () =>\n defineVersions().version('1.0.0', buildProvider()).build();\n\nexport { versions };\n", "import { ProviderBuilder } from '@rango-dev/wallets-core';\n\nimport { metadata, WALLET_ID, XVERSE_INJECTION_DELAY_MS } from './constants.js';\nimport { utxo } from './namespaces/utxo.js';\nimport { xverse as unisatInstance } from './utils.js';\n\nconst buildProvider = () =>\n new ProviderBuilder(WALLET_ID)\n .init(function (context) {\n const [, setState] = context.state();\n // TODO: We should remove this after we solved not initiating issue.\n setTimeout(() => {\n if (unisatInstance()) {\n setState('installed', true);\n console.debug('[xverse] instance detected.', context);\n }\n }, XVERSE_INJECTION_DELAY_MS);\n })\n .config('metadata', metadata)\n .add('utxo', utxo)\n .build();\n\nexport { buildProvider };\n", "import type { BlockchainMeta, TransferBlockchainMeta } from 'rango-types';\n\nimport { type ProviderMetadata } from '@rango-dev/wallets-core';\nimport { Networks } from '@rango-dev/wallets-shared';\n\nimport getSigners from './signer.js';\nimport { getInstanceOrThrow } from './utils.js';\n\nexport const XVERSE_INJECTION_DELAY_MS = 1000;\nexport const XVERSE_ACCESS_DENIED_ERROR_CODE = -32002;\nexport const WALLET_ID = 'xverse';\n\nexport const metadata: ProviderMetadata = {\n name: 'xverse',\n icon: 'https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/xverse/icon.svg',\n extensions: {\n chrome:\n 'https://chromewebstore.google.com/detail/idnnbdplmphpflfnlkomgpfbpcgelopg',\n homepage: 'https://www.xverse.app/',\n },\n properties: [\n {\n name: 'namespaces',\n value: {\n selection: 'single',\n data: [\n {\n label: 'BTC',\n value: 'UTXO',\n id: 'BTC',\n getSupportedChains: (allBlockchains: BlockchainMeta[]) =>\n allBlockchains.filter(\n (chain): chain is TransferBlockchainMeta =>\n chain.name === Networks.BTC\n ),\n },\n ],\n },\n },\n {\n name: 'signers',\n value: { getSigners: async () => getSigners(getInstanceOrThrow()) },\n },\n ],\n};\n", "import type { Provider } from './types.js';\nimport type { SignerFactory } from 'rango-types';\n\nimport { LegacyNetworks as Networks } from '@rango-dev/wallets-core/legacy';\nimport { getNetworkInstance } from '@rango-dev/wallets-shared';\nimport { DefaultSignerFactory, TransactionType as TxType } from 'rango-types';\n\nimport { BTCSigner } from './signers/utxoSigner.js';\n\nexport default async function getSigners(\n provider: Provider\n): Promise<SignerFactory> {\n const bitcoinInstance = getNetworkInstance(provider, Networks.BTC);\n\n const signers = new DefaultSignerFactory();\n signers.registerSigner(TxType.TRANSFER, new BTCSigner(bitcoinInstance));\n return signers;\n}\n", "import type { ProviderAPI } from '@rango-dev/wallets-core/namespaces/utxo';\nimport type { GenericSigner, Transfer } from 'rango-types';\n\nimport { Networks } from '@rango-dev/wallets-shared';\nimport { SignerError } from 'rango-types';\n\nexport class BTCSigner implements GenericSigner<Transfer> {\n private provider: ProviderAPI;\n constructor(provider: ProviderAPI) {\n this.provider = provider;\n }\n\n async signMessage(): Promise<string> {\n throw SignerError.UnimplementedError('signMessage');\n }\n\n async signAndSendTx(tx: Transfer): Promise<{ hash: string }> {\n const { asset, psbt } = tx;\n if (!psbt) {\n throw new Error(\n 'No PSBT found to sign. Ensure a valid PSBT is provided.'\n );\n }\n\n if (asset.blockchain !== Networks.BTC) {\n throw new Error(\n `Signing ${asset.blockchain} transaction is not implemented by the signer.`\n );\n }\n\n // 2. Build sign inputs\n const signInputs: Record<string, number[]> = {};\n\n psbt.inputsToSign.forEach(({ address, signingIndexes }) => {\n signInputs[address] = signingIndexes;\n });\n\n // 3. Sign (& broadcast)\n const signPsbtResult = await this.provider.request('signPsbt', {\n psbt: psbt.unsignedPsbtBase64,\n signInputs,\n broadcast: true,\n });\n\n if (signPsbtResult?.error) {\n throw new Error(\n signPsbtResult.error.message || 'Error during transaction sign'\n );\n }\n if (!signPsbtResult?.result?.txid) {\n throw new Error('Transaction not found!');\n }\n\n return { hash: signPsbtResult.result.txid };\n }\n}\n", "import type { Provider, XVerseResponse } from './types.js';\nimport type { ProviderAPI } from '@rango-dev/wallets-core/namespaces/utxo';\n\nimport { LegacyNetworks } from '@rango-dev/wallets-core/legacy';\n\nexport function xverse(): Provider | null {\n const { XverseProviders } = window;\n\n if (!XverseProviders) {\n return null;\n }\n\n const instances: Provider = new Map();\n\n if (XverseProviders.BitcoinProvider) {\n instances.set(LegacyNetworks.BTC, XverseProviders.BitcoinProvider);\n }\n\n return instances;\n}\n\nexport function getInstanceOrThrow(): Provider {\n const instances = xverse();\n\n if (!instances) {\n throw new Error('Xverse is not injected. Please check your wallet.');\n }\n\n return instances;\n}\n\nexport function bitcoinXverse(): ProviderAPI {\n const instances = xverse();\n const bitcoinInstance = instances?.get(LegacyNetworks.BTC);\n\n if (!bitcoinInstance) {\n throw new Error('Xverse not injected. Please check your wallet.');\n }\n\n return bitcoinInstance;\n}\nexport async function getBitcoinAccounts(): Promise<XVerseResponse> {\n const instance = bitcoinXverse();\n const requestResult = await instance.request('wallet_connect', {\n addresses: ['payment'],\n network: 'Mainnet',\n });\n\n if (requestResult.error?.message) {\n throw new Error(requestResult.error.message);\n }\n\n return requestResult;\n}\n", "import { NamespaceBuilder } from '@rango-dev/wallets-core';\nimport {\n builders as commonBuilders,\n standardizeAndThrowError,\n} from '@rango-dev/wallets-core/namespaces/common';\nimport {\n utils,\n type UtxoActions,\n} from '@rango-dev/wallets-core/namespaces/utxo';\nimport { builders } from '@rango-dev/wallets-core/namespaces/utxo';\n\nimport { utxoBuilders } from '../builders/utxo.js';\nimport { WALLET_ID } from '../constants.js';\nimport { bitcoinXverse, getBitcoinAccounts } from '../utils.js';\n\nconst [changeAccountSubscriber, changeAccountCleanup] = utxoBuilders\n .changeAccountSubscriber(bitcoinXverse)\n .build();\n\nconst canEagerConnect = utxoBuilders.canEagerConnect(bitcoinXverse).build();\n\nconst connect = builders\n .connect()\n .action(async function () {\n const accountsResult = await getBitcoinAccounts();\n\n if (accountsResult.result?.addresses?.length === 0) {\n throw new Error(\"Couldn't find any address!\");\n }\n return utils.formatAccountsToCAIP(\n accountsResult.result.addresses.map((address) => address.address)\n );\n })\n .before(changeAccountSubscriber)\n .or(changeAccountCleanup)\n .or(standardizeAndThrowError)\n .build();\n\nconst disconnect = commonBuilders\n .disconnect<UtxoActions>()\n .after(changeAccountCleanup)\n .build();\n\nconst utxo = new NamespaceBuilder<UtxoActions>('UTXO', WALLET_ID)\n .action(connect)\n .action(disconnect)\n .action(canEagerConnect)\n .build();\n\nexport { utxo };\n", "import type { XVerseEvent } from '../types.js';\n\nimport { ActionBuilder } from '@rango-dev/wallets-core';\nimport { ChangeAccountSubscriberBuilder } from '@rango-dev/wallets-core/namespaces/common';\nimport {\n type ProviderAPI,\n utils,\n type UtxoActions,\n} from '@rango-dev/wallets-core/namespaces/utxo';\n\nimport { XVERSE_ACCESS_DENIED_ERROR_CODE } from '../constants.js';\n\nexport const changeAccountSubscriber = (getInstance: () => ProviderAPI) =>\n new ChangeAccountSubscriberBuilder<XVerseEvent, ProviderAPI>()\n .getInstance(getInstance)\n /*\n * Xverse wallet may call the `changeAccount` event with `empty` value\n * but we shouldn't disconnect in this case.\n */\n .onSwitchAccount((event) => {\n if (!event.payload?.addresses?.length) {\n event.preventDefault();\n }\n })\n .format(async (_, event) => {\n return utils.formatAccountsToCAIP(\n event.addresses\n .filter((address) => address.purpose === 'payment')\n .map((address) => address.address)\n );\n })\n .addEventListener((instance, callback) => {\n return instance.addListener('accountChange', callback);\n })\n .removeEventListener((_, __) => {\n // it will be removed by the main class\n });\n\nfunction canEagerConnect(getInstance: () => ProviderAPI) {\n return new ActionBuilder<UtxoActions, 'canEagerConnect'>(\n 'canEagerConnect'\n ).action(async () => {\n const instance = getInstance();\n try {\n const addressesResponse = await instance.request('getAddresses', {\n purposes: ['payment'],\n });\n if (addressesResponse.error?.code === XVERSE_ACCESS_DENIED_ERROR_CODE) {\n return false;\n }\n return !!addressesResponse.result?.addresses?.length;\n } catch {\n return false;\n }\n });\n}\n\nexport const utxoBuilders = { changeAccountSubscriber, canEagerConnect };\n"],
5
+ "mappings": "+EAAA,OAAS,kBAAAA,MAAsB,gCCA/B,OAAS,mBAAAC,MAAuB,0BCEhC,MAAsC,0BACtC,OAAS,YAAAC,MAAgB,4BCAzB,OAAS,kBAAkBC,MAAgB,iCAC3C,OAAS,sBAAAC,MAA0B,4BACnC,OAAS,wBAAAC,EAAsB,mBAAmBC,MAAc,cCFhE,OAAS,YAAAC,MAAgB,4BACzB,OAAS,eAAAC,MAAmB,cAErB,IAAMC,EAAN,KAAmD,CAN1D,MAM0D,CAAAC,EAAA,kBAChD,SACR,YAAYC,EAAuB,CACjC,KAAK,SAAWA,CAClB,CAEA,MAAM,aAA+B,CACnC,MAAMC,EAAY,mBAAmB,aAAa,CACpD,CAEA,MAAM,cAAcC,EAAyC,CAC3D,GAAM,CAAE,MAAAC,EAAO,KAAAC,CAAK,EAAIF,EACxB,GAAI,CAACE,EACH,MAAM,IAAI,MACR,yDACF,EAGF,GAAID,EAAM,aAAeE,EAAS,IAChC,MAAM,IAAI,MACR,WAAWF,EAAM,UAAU,gDAC7B,EAIF,IAAMG,EAAuC,CAAC,EAE9CF,EAAK,aAAa,QAAQ,CAAC,CAAE,QAAAG,EAAS,eAAAC,CAAe,IAAM,CACzDF,EAAWC,CAAO,EAAIC,CACxB,CAAC,EAGD,IAAMC,EAAiB,MAAM,KAAK,SAAS,QAAQ,WAAY,CAC7D,KAAML,EAAK,mBACX,WAAAE,EACA,UAAW,EACb,CAAC,EAED,GAAIG,GAAgB,MAClB,MAAM,IAAI,MACRA,EAAe,MAAM,SAAW,+BAClC,EAEF,GAAI,CAACA,GAAgB,QAAQ,KAC3B,MAAM,IAAI,MAAM,wBAAwB,EAG1C,MAAO,CAAE,KAAMA,EAAe,OAAO,IAAK,CAC5C,CACF,ED9CA,eAAOC,EACLC,EACwB,CACxB,IAAMC,EAAkBC,EAAmBF,EAAUG,EAAS,GAAG,EAE3DC,EAAU,IAAIC,EACpB,OAAAD,EAAQ,eAAeE,EAAO,SAAU,IAAIC,EAAUN,CAAe,CAAC,EAC/DG,CACT,CAR8BI,EAAAT,EAAA,cEN9B,OAAS,kBAAAU,MAAsB,iCAExB,SAASC,GAA0B,CACxC,GAAM,CAAE,gBAAAC,CAAgB,EAAI,OAE5B,GAAI,CAACA,EACH,OAAO,KAGT,IAAMC,EAAsB,IAAI,IAEhC,OAAID,EAAgB,iBAClBC,EAAU,IAAIC,EAAe,IAAKF,EAAgB,eAAe,EAG5DC,CACT,CAdgBE,EAAAJ,EAAA,UAgBT,SAASK,GAA+B,CAC7C,IAAMH,EAAYF,EAAO,EAEzB,GAAI,CAACE,EACH,MAAM,IAAI,MAAM,mDAAmD,EAGrE,OAAOA,CACT,CARgBE,EAAAC,EAAA,sBAUT,SAASC,GAA6B,CAE3C,IAAMC,EADYP,EAAO,GACU,IAAIG,EAAe,GAAG,EAEzD,GAAI,CAACI,EACH,MAAM,IAAI,MAAM,gDAAgD,EAGlE,OAAOA,CACT,CATgBH,EAAAE,EAAA,iBAUhB,eAAsBE,GAA8C,CAElE,IAAMC,EAAgB,MADLH,EAAc,EACM,QAAQ,iBAAkB,CAC7D,UAAW,CAAC,SAAS,EACrB,QAAS,SACX,CAAC,EAED,GAAIG,EAAc,OAAO,QACvB,MAAM,IAAI,MAAMA,EAAc,MAAM,OAAO,EAG7C,OAAOA,CACT,CAZsBL,EAAAI,EAAA,sBHjCf,IAAME,EAA4B,IAC5BC,EAAkC,OAClCC,EAAY,SAEZC,EAA6B,CACxC,KAAM,SACN,KAAM,uFACN,WAAY,CACV,OACE,4EACF,SAAU,yBACZ,EACA,WAAY,CACV,CACE,KAAM,aACN,MAAO,CACL,UAAW,SACX,KAAM,CACJ,CACE,MAAO,MACP,MAAO,OACP,GAAI,MACJ,mBAAqBC,GACnBA,EAAe,OACZC,GACCA,EAAM,OAASC,EAAS,GAC5B,CACJ,CACF,CACF,CACF,EACA,CACE,KAAM,UACN,MAAO,CAAE,WAAY,SAAYC,EAAWC,EAAmB,CAAC,CAAE,CACpE,CACF,CACF,EI5CA,OAAS,oBAAAC,MAAwB,0BACjC,OACE,YAAYC,EACZ,4BAAAC,MACK,4CACP,OACE,SAAAC,MAEK,0CACP,OAAS,YAAAC,MAAgB,0CCPzB,OAAS,iBAAAC,MAAqB,0BAC9B,OAAS,kCAAAC,MAAsC,4CAC/C,OAEE,SAAAC,MAEK,0CAIA,IAAMC,EAA0BC,EAACC,GACtC,IAAIC,EAAyD,EAC1D,YAAYD,CAAW,EAKvB,gBAAiBE,GAAU,CACrBA,EAAM,SAAS,WAAW,QAC7BA,EAAM,eAAe,CAEzB,CAAC,EACA,OAAO,MAAOC,EAAGD,IACTE,EAAM,qBACXF,EAAM,UACH,OAAQG,GAAYA,EAAQ,UAAY,SAAS,EACjD,IAAKA,GAAYA,EAAQ,OAAO,CACrC,CACD,EACA,iBAAiB,CAACC,EAAUC,IACpBD,EAAS,YAAY,gBAAiBC,CAAQ,CACtD,EACA,oBAAoB,CAACJ,EAAGK,IAAO,CAEhC,CAAC,EAxBkC,2BA0BvC,SAASC,EAAgBT,EAAgC,CACvD,OAAO,IAAIU,EACT,iBACF,EAAE,OAAO,SAAY,CACnB,IAAMJ,EAAWN,EAAY,EAC7B,GAAI,CACF,IAAMW,EAAoB,MAAML,EAAS,QAAQ,eAAgB,CAC/D,SAAU,CAAC,SAAS,CACtB,CAAC,EACD,OAAIK,EAAkB,OAAO,OAASC,EAC7B,GAEF,CAAC,CAACD,EAAkB,QAAQ,WAAW,MAChD,MAAQ,CACN,MAAO,EACT,CACF,CAAC,CACH,CAjBSZ,EAAAU,EAAA,mBAmBF,IAAMI,EAAe,CAAE,wBAAAf,EAAyB,gBAAAW,CAAgB,ED1CvE,GAAM,CAACK,EAAyBC,CAAoB,EAAIC,EACrD,wBAAwBC,CAAa,EACrC,MAAM,EAEHC,EAAkBF,EAAa,gBAAgBC,CAAa,EAAE,MAAM,EAEpEE,EAAUC,EACb,QAAQ,EACR,OAAO,gBAAkB,CACxB,IAAMC,EAAiB,MAAMC,EAAmB,EAEhD,GAAID,EAAe,QAAQ,WAAW,SAAW,EAC/C,MAAM,IAAI,MAAM,4BAA4B,EAE9C,OAAOE,EAAM,qBACXF,EAAe,OAAO,UAAU,IAAKG,GAAYA,EAAQ,OAAO,CAClE,CACF,CAAC,EACA,OAAOV,CAAuB,EAC9B,GAAGC,CAAoB,EACvB,GAAGU,CAAwB,EAC3B,MAAM,EAEHC,EAAaC,EAChB,WAAwB,EACxB,MAAMZ,CAAoB,EAC1B,MAAM,EAEHa,EAAO,IAAIC,EAA8B,OAAQC,CAAS,EAC7D,OAAOX,CAAO,EACd,OAAOO,CAAU,EACjB,OAAOR,CAAe,EACtB,MAAM,ELzCT,IAAMa,EAAgBC,EAAA,IACpB,IAAIC,EAAgBC,CAAS,EAC1B,KAAK,SAAUC,EAAS,CACvB,GAAM,CAAC,CAAEC,CAAQ,EAAID,EAAQ,MAAM,EAEnC,WAAW,IAAM,CACXE,EAAe,IACjBD,EAAS,YAAa,EAAI,EAC1B,QAAQ,MAAM,8BAA+BD,CAAO,EAExD,EAAGG,CAAyB,CAC9B,CAAC,EACA,OAAO,WAAYC,CAAQ,EAC3B,IAAI,OAAQC,CAAI,EAChB,MAAM,EAdW,iBDFtB,IAAMC,GAAWC,EAAA,IACfC,EAAe,EAAE,QAAQ,QAASC,EAAc,CAAC,EAAE,MAAM,EAD1C",
6
+ "names": ["defineVersions", "ProviderBuilder", "Networks", "Networks", "getNetworkInstance", "DefaultSignerFactory", "TxType", "Networks", "SignerError", "BTCSigner", "__name", "provider", "SignerError", "tx", "asset", "psbt", "Networks", "signInputs", "address", "signingIndexes", "signPsbtResult", "getSigners", "provider", "bitcoinInstance", "getNetworkInstance", "Networks", "signers", "DefaultSignerFactory", "TxType", "BTCSigner", "__name", "LegacyNetworks", "xverse", "XverseProviders", "instances", "LegacyNetworks", "__name", "getInstanceOrThrow", "bitcoinXverse", "bitcoinInstance", "getBitcoinAccounts", "requestResult", "XVERSE_INJECTION_DELAY_MS", "XVERSE_ACCESS_DENIED_ERROR_CODE", "WALLET_ID", "metadata", "allBlockchains", "chain", "Networks", "getSigners", "getInstanceOrThrow", "NamespaceBuilder", "commonBuilders", "standardizeAndThrowError", "utils", "builders", "ActionBuilder", "ChangeAccountSubscriberBuilder", "utils", "changeAccountSubscriber", "__name", "getInstance", "ChangeAccountSubscriberBuilder", "event", "_", "utils", "address", "instance", "callback", "__", "canEagerConnect", "ActionBuilder", "addressesResponse", "XVERSE_ACCESS_DENIED_ERROR_CODE", "utxoBuilders", "changeAccountSubscriber", "changeAccountCleanup", "utxoBuilders", "bitcoinXverse", "canEagerConnect", "connect", "builders", "accountsResult", "getBitcoinAccounts", "utils", "address", "standardizeAndThrowError", "disconnect", "commonBuilders", "utxo", "NamespaceBuilder", "WALLET_ID", "buildProvider", "__name", "ProviderBuilder", "WALLET_ID", "context", "setState", "xverse", "XVERSE_INJECTION_DELAY_MS", "metadata", "utxo", "versions", "__name", "defineVersions", "buildProvider"]
7
+ }
@@ -0,0 +1,4 @@
1
+ import { type UtxoActions } from '@rango-dev/wallets-core/namespaces/utxo';
2
+ declare const utxo: import("@rango-dev/wallets-core").ProxiedNamespace<UtxoActions>;
3
+ export { utxo };
4
+ //# sourceMappingURL=utxo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.d.ts","sourceRoot":"","sources":["../../src/namespaces/utxo.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,WAAW,EACjB,MAAM,yCAAyC,CAAC;AAmCjD,QAAA,MAAM,IAAI,iEAIA,CAAC;AAEX,OAAO,EAAE,IAAI,EAAE,CAAC"}
@@ -0,0 +1 @@
1
+ {"inputs":{"src/signers/utxoSigner.ts":{"bytes":1572,"imports":[{"path":"@rango-dev/wallets-shared","kind":"import-statement","external":true},{"path":"rango-types","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"src/signer.ts":{"bytes":673,"imports":[{"path":"@rango-dev/wallets-core/legacy","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-shared","kind":"import-statement","external":true},{"path":"rango-types","kind":"import-statement","external":true},{"path":"src/signers/utxoSigner.ts","kind":"import-statement","original":"./signers/utxoSigner.js"},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"src/utils.ts":{"bytes":1340,"imports":[{"path":"@rango-dev/wallets-core/legacy","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"src/constants.ts":{"bytes":1322,"imports":[{"path":"@rango-dev/wallets-core","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-shared","kind":"import-statement","external":true},{"path":"src/signer.ts","kind":"import-statement","original":"./signer.js"},{"path":"src/utils.ts","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"src/builders/utxo.ts":{"bytes":1862,"imports":[{"path":"@rango-dev/wallets-core","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/common","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/utxo","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants.js"},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"src/namespaces/utxo.ts":{"bytes":1444,"imports":[{"path":"@rango-dev/wallets-core","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/common","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/utxo","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/utxo","kind":"import-statement","external":true},{"path":"src/builders/utxo.ts","kind":"import-statement","original":"../builders/utxo.js"},{"path":"src/constants.ts","kind":"import-statement","original":"../constants.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"src/provider.ts":{"bytes":766,"imports":[{"path":"@rango-dev/wallets-core","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"./constants.js"},{"path":"src/namespaces/utxo.ts","kind":"import-statement","original":"./namespaces/utxo.js"},{"path":"src/utils.ts","kind":"import-statement","original":"./utils.js"},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"src/mod.ts":{"bytes":220,"imports":[{"path":"@rango-dev/wallets-core/utils","kind":"import-statement","external":true},{"path":"src/provider.ts","kind":"import-statement","original":"./provider.js"},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/mod.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":15383},"dist/mod.js":{"imports":[{"path":"@rango-dev/wallets-core/utils","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-shared","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/legacy","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-shared","kind":"import-statement","external":true},{"path":"rango-types","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-shared","kind":"import-statement","external":true},{"path":"rango-types","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/legacy","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/common","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/utxo","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/utxo","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/common","kind":"import-statement","external":true},{"path":"@rango-dev/wallets-core/namespaces/utxo","kind":"import-statement","external":true}],"exports":["versions"],"entryPoint":"src/mod.ts","inputs":{"src/mod.ts":{"bytesInOutput":121},"src/provider.ts":{"bytesInOutput":268},"src/constants.ts":{"bytesInOutput":561},"src/signer.ts":{"bytesInOutput":309},"src/signers/utxoSigner.ts":{"bytesInOutput":818},"src/utils.ts":{"bytesInOutput":673},"src/namespaces/utxo.ts":{"bytesInOutput":691},"src/builders/utxo.ts":{"bytesInOutput":828}},"bytes":4404}}}
@@ -0,0 +1,3 @@
1
+ declare const buildProvider: () => import("@rango-dev/wallets-core").Provider;
2
+ export { buildProvider };
3
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,aAAa,kDAcP,CAAC;AAEb,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Provider } from './types.js';
2
+ import type { SignerFactory } from 'rango-types';
3
+ export default function getSigners(provider: Provider): Promise<SignerFactory>;
4
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQjD,wBAA8B,UAAU,CACtC,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,aAAa,CAAC,CAMxB"}
@@ -0,0 +1,11 @@
1
+ import type { ProviderAPI } from '@rango-dev/wallets-core/namespaces/utxo';
2
+ import type { GenericSigner, Transfer } from 'rango-types';
3
+ export declare class BTCSigner implements GenericSigner<Transfer> {
4
+ private provider;
5
+ constructor(provider: ProviderAPI);
6
+ signMessage(): Promise<string>;
7
+ signAndSendTx(tx: Transfer): Promise<{
8
+ hash: string;
9
+ }>;
10
+ }
11
+ //# sourceMappingURL=utxoSigner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxoSigner.d.ts","sourceRoot":"","sources":["../../src/signers/utxoSigner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK3D,qBAAa,SAAU,YAAW,aAAa,CAAC,QAAQ,CAAC;IACvD,OAAO,CAAC,QAAQ,CAAc;gBAClB,QAAQ,EAAE,WAAW;IAI3B,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAI9B,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAuC7D"}
@@ -0,0 +1,39 @@
1
+ import type { LegacyNetworks } from '@rango-dev/wallets-core/legacy';
2
+ import type { ProviderAPI } from '@rango-dev/wallets-core/namespaces/utxo';
3
+ type XVerseAddress = {
4
+ address: string;
5
+ publicKey: string;
6
+ purpose: 'ordinals' | 'payment';
7
+ addressType: 'p2tr' | 'p2wpkh' | 'p2sh';
8
+ walletType: 'software' | 'hardware';
9
+ };
10
+ export type XVerseResponse = {
11
+ error?: {
12
+ message: string;
13
+ code: string;
14
+ };
15
+ result: {
16
+ addresses: XVerseAddress[];
17
+ network: {
18
+ bitcoin: {
19
+ name: 'Mainnet';
20
+ };
21
+ spark: {
22
+ name: 'mainnet';
23
+ };
24
+ stacks: {
25
+ name: 'mainnet';
26
+ };
27
+ };
28
+ };
29
+ };
30
+ export type XVerseEvent = {
31
+ addresses: XVerseAddress[];
32
+ type: 'accountChange';
33
+ };
34
+ export type ProviderObject = {
35
+ [LegacyNetworks.BTC]: ProviderAPI;
36
+ };
37
+ export type Provider = Map<keyof ProviderObject, ProviderObject[keyof ProviderObject]>;
38
+ export {};
39
+ //# 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,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAE3E,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,UAAU,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IACxC,UAAU,EAAE,UAAU,GAAG,UAAU,CAAC;CACrC,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,EAAE;QACN,SAAS,EAAE,aAAa,EAAE,CAAC;QAE3B,OAAO,EAAE;YACP,OAAO,EAAE;gBAAE,IAAI,EAAE,SAAS,CAAA;aAAE,CAAC;YAC7B,KAAK,EAAE;gBAAE,IAAI,EAAE,SAAS,CAAA;aAAE,CAAC;YAC3B,MAAM,EAAE;gBAAE,IAAI,EAAE,SAAS,CAAA;aAAE,CAAC;SAC7B,CAAC;KACH,CAAC;CACH,CAAC;AACF,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,IAAI,EAAE,eAAe,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;CACnC,CAAC;AACF,MAAM,MAAM,QAAQ,GAAG,GAAG,CACxB,MAAM,cAAc,EACpB,cAAc,CAAC,MAAM,cAAc,CAAC,CACrC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Provider, XVerseResponse } from './types.js';
2
+ import type { ProviderAPI } from '@rango-dev/wallets-core/namespaces/utxo';
3
+ export declare function xverse(): Provider | null;
4
+ export declare function getInstanceOrThrow(): Provider;
5
+ export declare function bitcoinXverse(): ProviderAPI;
6
+ export declare function getBitcoinAccounts(): Promise<XVerseResponse>;
7
+ //# 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,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAI3E,wBAAgB,MAAM,IAAI,QAAQ,GAAG,IAAI,CAcxC;AAED,wBAAgB,kBAAkB,IAAI,QAAQ,CAQ7C;AAED,wBAAgB,aAAa,IAAI,WAAW,CAS3C;AACD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC,CAYlE"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@rango-dev/provider-xverse",
3
+ "version": "0.0.2-next.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "source": "./src/mod.ts",
7
+ "main": "./dist/mod.js",
8
+ "exports": {
9
+ ".": "./dist/mod.js"
10
+ },
11
+ "typings": "dist/mod.d.ts",
12
+ "files": [
13
+ "dist",
14
+ "src"
15
+ ],
16
+ "scripts": {
17
+ "build": "node ../../scripts/build/command.mjs --path wallets/provider-xverse --inputs src/mod.ts",
18
+ "ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json",
19
+ "clean": "rimraf dist",
20
+ "format": "prettier --write '{.,src}/**/*.{ts,tsx}'",
21
+ "lint": "eslint \"**/*.{ts,tsx}\""
22
+ },
23
+ "dependencies": {
24
+ "@rango-dev/wallets-core": "^0.53.1-next.0",
25
+ "@rango-dev/wallets-shared": "^0.54.2-next.1",
26
+ "rango-types": "^0.1.89"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ }
31
+ }
package/readme.md ADDED
@@ -0,0 +1,27 @@
1
+ # Xverse Provider
2
+
3
+ Xverse integration for hub.
4
+ [Homepage](https://www.xverse.app/) | [Docs](https://docs.xverse.app/sats-connect)
5
+
6
+ More about implementation status can be found [here](../readme.md).
7
+
8
+ ## Implementation notes/limitation
9
+
10
+ ### Group
11
+
12
+ #### ⚠️ UTXO
13
+
14
+ Only supports **Bitcoin**.
15
+
16
+ ### Feature
17
+
18
+ #### ⚠️ Disconnect Handling
19
+ The wallet's disconnect event is not working properly.
20
+ As a result, the dApp remains unaware of the disconnection, and the session continues until the user manually disconnects from within the dApp.
21
+ #### ⚠️ Switch Account
22
+
23
+ Currently, switching accounts on Xverse is not working correctly, which causes the wallet to disconnect from the dApp.
24
+
25
+ ---
26
+
27
+ More wallet information can be found in [readme.md](../readme.md).
@@ -0,0 +1,58 @@
1
+ import type { XVerseEvent } from '../types.js';
2
+
3
+ import { ActionBuilder } from '@rango-dev/wallets-core';
4
+ import { ChangeAccountSubscriberBuilder } from '@rango-dev/wallets-core/namespaces/common';
5
+ import {
6
+ type ProviderAPI,
7
+ utils,
8
+ type UtxoActions,
9
+ } from '@rango-dev/wallets-core/namespaces/utxo';
10
+
11
+ import { XVERSE_ACCESS_DENIED_ERROR_CODE } from '../constants.js';
12
+
13
+ export const changeAccountSubscriber = (getInstance: () => ProviderAPI) =>
14
+ new ChangeAccountSubscriberBuilder<XVerseEvent, ProviderAPI>()
15
+ .getInstance(getInstance)
16
+ /*
17
+ * Xverse wallet may call the `changeAccount` event with `empty` value
18
+ * but we shouldn't disconnect in this case.
19
+ */
20
+ .onSwitchAccount((event) => {
21
+ if (!event.payload?.addresses?.length) {
22
+ event.preventDefault();
23
+ }
24
+ })
25
+ .format(async (_, event) => {
26
+ return utils.formatAccountsToCAIP(
27
+ event.addresses
28
+ .filter((address) => address.purpose === 'payment')
29
+ .map((address) => address.address)
30
+ );
31
+ })
32
+ .addEventListener((instance, callback) => {
33
+ return instance.addListener('accountChange', callback);
34
+ })
35
+ .removeEventListener((_, __) => {
36
+ // it will be removed by the main class
37
+ });
38
+
39
+ function canEagerConnect(getInstance: () => ProviderAPI) {
40
+ return new ActionBuilder<UtxoActions, 'canEagerConnect'>(
41
+ 'canEagerConnect'
42
+ ).action(async () => {
43
+ const instance = getInstance();
44
+ try {
45
+ const addressesResponse = await instance.request('getAddresses', {
46
+ purposes: ['payment'],
47
+ });
48
+ if (addressesResponse.error?.code === XVERSE_ACCESS_DENIED_ERROR_CODE) {
49
+ return false;
50
+ }
51
+ return !!addressesResponse.result?.addresses?.length;
52
+ } catch {
53
+ return false;
54
+ }
55
+ });
56
+ }
57
+
58
+ export const utxoBuilders = { changeAccountSubscriber, canEagerConnect };
@@ -0,0 +1,45 @@
1
+ import type { BlockchainMeta, TransferBlockchainMeta } from 'rango-types';
2
+
3
+ import { type ProviderMetadata } from '@rango-dev/wallets-core';
4
+ import { Networks } from '@rango-dev/wallets-shared';
5
+
6
+ import getSigners from './signer.js';
7
+ import { getInstanceOrThrow } from './utils.js';
8
+
9
+ export const XVERSE_INJECTION_DELAY_MS = 1000;
10
+ export const XVERSE_ACCESS_DENIED_ERROR_CODE = -32002;
11
+ export const WALLET_ID = 'xverse';
12
+
13
+ export const metadata: ProviderMetadata = {
14
+ name: 'xverse',
15
+ icon: 'https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/xverse/icon.svg',
16
+ extensions: {
17
+ chrome:
18
+ 'https://chromewebstore.google.com/detail/idnnbdplmphpflfnlkomgpfbpcgelopg',
19
+ homepage: 'https://www.xverse.app/',
20
+ },
21
+ properties: [
22
+ {
23
+ name: 'namespaces',
24
+ value: {
25
+ selection: 'single',
26
+ data: [
27
+ {
28
+ label: 'BTC',
29
+ value: 'UTXO',
30
+ id: 'BTC',
31
+ getSupportedChains: (allBlockchains: BlockchainMeta[]) =>
32
+ allBlockchains.filter(
33
+ (chain): chain is TransferBlockchainMeta =>
34
+ chain.name === Networks.BTC
35
+ ),
36
+ },
37
+ ],
38
+ },
39
+ },
40
+ {
41
+ name: 'signers',
42
+ value: { getSigners: async () => getSigners(getInstanceOrThrow()) },
43
+ },
44
+ ],
45
+ };
package/src/mod.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { defineVersions } from '@rango-dev/wallets-core/utils';
2
+
3
+ import { buildProvider } from './provider.js';
4
+
5
+ const versions = () =>
6
+ defineVersions().version('1.0.0', buildProvider()).build();
7
+
8
+ export { versions };
@@ -0,0 +1,50 @@
1
+ import { NamespaceBuilder } from '@rango-dev/wallets-core';
2
+ import {
3
+ builders as commonBuilders,
4
+ standardizeAndThrowError,
5
+ } from '@rango-dev/wallets-core/namespaces/common';
6
+ import {
7
+ utils,
8
+ type UtxoActions,
9
+ } from '@rango-dev/wallets-core/namespaces/utxo';
10
+ import { builders } from '@rango-dev/wallets-core/namespaces/utxo';
11
+
12
+ import { utxoBuilders } from '../builders/utxo.js';
13
+ import { WALLET_ID } from '../constants.js';
14
+ import { bitcoinXverse, getBitcoinAccounts } from '../utils.js';
15
+
16
+ const [changeAccountSubscriber, changeAccountCleanup] = utxoBuilders
17
+ .changeAccountSubscriber(bitcoinXverse)
18
+ .build();
19
+
20
+ const canEagerConnect = utxoBuilders.canEagerConnect(bitcoinXverse).build();
21
+
22
+ const connect = builders
23
+ .connect()
24
+ .action(async function () {
25
+ const accountsResult = await getBitcoinAccounts();
26
+
27
+ if (accountsResult.result?.addresses?.length === 0) {
28
+ throw new Error("Couldn't find any address!");
29
+ }
30
+ return utils.formatAccountsToCAIP(
31
+ accountsResult.result.addresses.map((address) => address.address)
32
+ );
33
+ })
34
+ .before(changeAccountSubscriber)
35
+ .or(changeAccountCleanup)
36
+ .or(standardizeAndThrowError)
37
+ .build();
38
+
39
+ const disconnect = commonBuilders
40
+ .disconnect<UtxoActions>()
41
+ .after(changeAccountCleanup)
42
+ .build();
43
+
44
+ const utxo = new NamespaceBuilder<UtxoActions>('UTXO', WALLET_ID)
45
+ .action(connect)
46
+ .action(disconnect)
47
+ .action(canEagerConnect)
48
+ .build();
49
+
50
+ export { utxo };
@@ -0,0 +1,23 @@
1
+ import { ProviderBuilder } from '@rango-dev/wallets-core';
2
+
3
+ import { metadata, WALLET_ID, XVERSE_INJECTION_DELAY_MS } from './constants.js';
4
+ import { utxo } from './namespaces/utxo.js';
5
+ import { xverse as unisatInstance } from './utils.js';
6
+
7
+ const buildProvider = () =>
8
+ new ProviderBuilder(WALLET_ID)
9
+ .init(function (context) {
10
+ const [, setState] = context.state();
11
+ // TODO: We should remove this after we solved not initiating issue.
12
+ setTimeout(() => {
13
+ if (unisatInstance()) {
14
+ setState('installed', true);
15
+ console.debug('[xverse] instance detected.', context);
16
+ }
17
+ }, XVERSE_INJECTION_DELAY_MS);
18
+ })
19
+ .config('metadata', metadata)
20
+ .add('utxo', utxo)
21
+ .build();
22
+
23
+ export { buildProvider };
package/src/signer.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { Provider } from './types.js';
2
+ import type { SignerFactory } from 'rango-types';
3
+
4
+ import { LegacyNetworks as Networks } from '@rango-dev/wallets-core/legacy';
5
+ import { getNetworkInstance } from '@rango-dev/wallets-shared';
6
+ import { DefaultSignerFactory, TransactionType as TxType } from 'rango-types';
7
+
8
+ import { BTCSigner } from './signers/utxoSigner.js';
9
+
10
+ export default async function getSigners(
11
+ provider: Provider
12
+ ): Promise<SignerFactory> {
13
+ const bitcoinInstance = getNetworkInstance(provider, Networks.BTC);
14
+
15
+ const signers = new DefaultSignerFactory();
16
+ signers.registerSigner(TxType.TRANSFER, new BTCSigner(bitcoinInstance));
17
+ return signers;
18
+ }
@@ -0,0 +1,56 @@
1
+ import type { ProviderAPI } from '@rango-dev/wallets-core/namespaces/utxo';
2
+ import type { GenericSigner, Transfer } from 'rango-types';
3
+
4
+ import { Networks } from '@rango-dev/wallets-shared';
5
+ import { SignerError } from 'rango-types';
6
+
7
+ export class BTCSigner implements GenericSigner<Transfer> {
8
+ private provider: ProviderAPI;
9
+ constructor(provider: ProviderAPI) {
10
+ this.provider = provider;
11
+ }
12
+
13
+ async signMessage(): Promise<string> {
14
+ throw SignerError.UnimplementedError('signMessage');
15
+ }
16
+
17
+ async signAndSendTx(tx: Transfer): Promise<{ hash: string }> {
18
+ const { asset, psbt } = tx;
19
+ if (!psbt) {
20
+ throw new Error(
21
+ 'No PSBT found to sign. Ensure a valid PSBT is provided.'
22
+ );
23
+ }
24
+
25
+ if (asset.blockchain !== Networks.BTC) {
26
+ throw new Error(
27
+ `Signing ${asset.blockchain} transaction is not implemented by the signer.`
28
+ );
29
+ }
30
+
31
+ // 2. Build sign inputs
32
+ const signInputs: Record<string, number[]> = {};
33
+
34
+ psbt.inputsToSign.forEach(({ address, signingIndexes }) => {
35
+ signInputs[address] = signingIndexes;
36
+ });
37
+
38
+ // 3. Sign (& broadcast)
39
+ const signPsbtResult = await this.provider.request('signPsbt', {
40
+ psbt: psbt.unsignedPsbtBase64,
41
+ signInputs,
42
+ broadcast: true,
43
+ });
44
+
45
+ if (signPsbtResult?.error) {
46
+ throw new Error(
47
+ signPsbtResult.error.message || 'Error during transaction sign'
48
+ );
49
+ }
50
+ if (!signPsbtResult?.result?.txid) {
51
+ throw new Error('Transaction not found!');
52
+ }
53
+
54
+ return { hash: signPsbtResult.result.txid };
55
+ }
56
+ }
package/src/types.ts ADDED
@@ -0,0 +1,37 @@
1
+ import type { LegacyNetworks } from '@rango-dev/wallets-core/legacy';
2
+ import type { ProviderAPI } from '@rango-dev/wallets-core/namespaces/utxo';
3
+
4
+ type XVerseAddress = {
5
+ address: string;
6
+ publicKey: string;
7
+ purpose: 'ordinals' | 'payment';
8
+ addressType: 'p2tr' | 'p2wpkh' | 'p2sh';
9
+ walletType: 'software' | 'hardware';
10
+ };
11
+ export type XVerseResponse = {
12
+ error?: {
13
+ message: string;
14
+ code: string;
15
+ };
16
+ result: {
17
+ addresses: XVerseAddress[];
18
+
19
+ network: {
20
+ bitcoin: { name: 'Mainnet' };
21
+ spark: { name: 'mainnet' };
22
+ stacks: { name: 'mainnet' };
23
+ };
24
+ };
25
+ };
26
+ export type XVerseEvent = {
27
+ addresses: XVerseAddress[];
28
+ type: 'accountChange';
29
+ };
30
+
31
+ export type ProviderObject = {
32
+ [LegacyNetworks.BTC]: ProviderAPI;
33
+ };
34
+ export type Provider = Map<
35
+ keyof ProviderObject,
36
+ ProviderObject[keyof ProviderObject]
37
+ >;
package/src/utils.ts ADDED
@@ -0,0 +1,54 @@
1
+ import type { Provider, XVerseResponse } from './types.js';
2
+ import type { ProviderAPI } from '@rango-dev/wallets-core/namespaces/utxo';
3
+
4
+ import { LegacyNetworks } from '@rango-dev/wallets-core/legacy';
5
+
6
+ export function xverse(): Provider | null {
7
+ const { XverseProviders } = window;
8
+
9
+ if (!XverseProviders) {
10
+ return null;
11
+ }
12
+
13
+ const instances: Provider = new Map();
14
+
15
+ if (XverseProviders.BitcoinProvider) {
16
+ instances.set(LegacyNetworks.BTC, XverseProviders.BitcoinProvider);
17
+ }
18
+
19
+ return instances;
20
+ }
21
+
22
+ export function getInstanceOrThrow(): Provider {
23
+ const instances = xverse();
24
+
25
+ if (!instances) {
26
+ throw new Error('Xverse is not injected. Please check your wallet.');
27
+ }
28
+
29
+ return instances;
30
+ }
31
+
32
+ export function bitcoinXverse(): ProviderAPI {
33
+ const instances = xverse();
34
+ const bitcoinInstance = instances?.get(LegacyNetworks.BTC);
35
+
36
+ if (!bitcoinInstance) {
37
+ throw new Error('Xverse not injected. Please check your wallet.');
38
+ }
39
+
40
+ return bitcoinInstance;
41
+ }
42
+ export async function getBitcoinAccounts(): Promise<XVerseResponse> {
43
+ const instance = bitcoinXverse();
44
+ const requestResult = await instance.request('wallet_connect', {
45
+ addresses: ['payment'],
46
+ network: 'Mainnet',
47
+ });
48
+
49
+ if (requestResult.error?.message) {
50
+ throw new Error(requestResult.error.message);
51
+ }
52
+
53
+ return requestResult;
54
+ }