@usebutr/sui 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ChainBase, PlatformDiscoverer, WalletAdapter, WalletCapabilities } from "@usebutr/core";
|
|
2
|
-
import {
|
|
2
|
+
import { WalletStandardWallet, WalletStandardWalletAccount } from "@usebutr/wallet-standard-shared";
|
|
3
3
|
|
|
4
4
|
//#region src/wallet-standard-types.d.ts
|
|
5
5
|
type SuiSignPersonalMessageInput = {
|
|
6
|
-
account: WalletStandardWalletAccount
|
|
6
|
+
account: WalletStandardWalletAccount;
|
|
7
7
|
message: Uint8Array;
|
|
8
8
|
};
|
|
9
9
|
type SuiSignPersonalMessageOutput = {
|
|
@@ -14,7 +14,7 @@ type SuiSignPersonalMessageFeature = {
|
|
|
14
14
|
signPersonalMessage(input: SuiSignPersonalMessageInput): Promise<SuiSignPersonalMessageOutput>;
|
|
15
15
|
};
|
|
16
16
|
type SuiSignTransactionInput = {
|
|
17
|
-
account: WalletStandardWalletAccount
|
|
17
|
+
account: WalletStandardWalletAccount;
|
|
18
18
|
chain: string;
|
|
19
19
|
transaction: {
|
|
20
20
|
toJSON(): Promise<string>;
|
|
@@ -28,7 +28,7 @@ type SuiSignTransactionFeature = {
|
|
|
28
28
|
signTransaction(input: SuiSignTransactionInput): Promise<SuiSignTransactionOutput>;
|
|
29
29
|
};
|
|
30
30
|
type SuiSignAndExecuteTransactionInput = {
|
|
31
|
-
account: WalletStandardWalletAccount
|
|
31
|
+
account: WalletStandardWalletAccount;
|
|
32
32
|
chain: string;
|
|
33
33
|
transaction: {
|
|
34
34
|
toJSON(): Promise<string>;
|
|
@@ -64,7 +64,7 @@ declare const slugify: (name: string) => string;
|
|
|
64
64
|
* has no "tell the wallet to switch network" RPC; the wallet's UI
|
|
65
65
|
* controls its global cluster setting.
|
|
66
66
|
*/
|
|
67
|
-
declare const buildSuiAdapter: (wallet: WalletStandardWallet
|
|
67
|
+
declare const buildSuiAdapter: (wallet: WalletStandardWallet,
|
|
68
68
|
/** Optional. Called with a function that pushes a synthetic
|
|
69
69
|
* `disconnected` event to all current subscribers. The discovery
|
|
70
70
|
* layer invokes it on Wallet Standard `unregister`. */
|
|
@@ -160,9 +160,9 @@ declare const suiDiscoverer: PlatformDiscoverer;
|
|
|
160
160
|
*/
|
|
161
161
|
declare module "@usebutr/core" {
|
|
162
162
|
interface SignerForPlatform {
|
|
163
|
-
sui: WalletStandardWallet
|
|
163
|
+
sui: WalletStandardWallet;
|
|
164
164
|
}
|
|
165
165
|
} //# sourceMappingURL=signer-augmentation.d.ts.map
|
|
166
166
|
//#endregion
|
|
167
|
-
export { SUI_CHAINS, SUI_CHAINS_LIST, type
|
|
167
|
+
export { SUI_CHAINS, SUI_CHAINS_LIST, type SuiSignAndExecuteTransactionFeature, type SuiSignAndExecuteTransactionInput, type SuiSignAndExecuteTransactionOutput, type SuiSignPersonalMessageFeature, type SuiSignPersonalMessageInput, type SuiSignPersonalMessageOutput, type SuiSignTransactionFeature, type SuiSignTransactionInput, type SuiSignTransactionOutput, type WalletStandardCapabilityInput, buildSuiAdapter, discoverSuiAdapters, resolveSuiCapabilities, slugify, suiDiscoverer };
|
|
168
168
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/wallet-standard-types.ts","../src/wallet-standard-adapter.ts","../src/wallet-standard.ts","../src/chains.ts","../src/capabilities.ts","../src/discoverer.ts","../src/signer-augmentation.ts"],"mappings":";;;;KAaK,2BAAA;EACH,OAAA,EAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/wallet-standard-types.ts","../src/wallet-standard-adapter.ts","../src/wallet-standard.ts","../src/chains.ts","../src/capabilities.ts","../src/discoverer.ts","../src/signer-augmentation.ts"],"mappings":";;;;KAaK,2BAAA;EACH,OAAA,EAAS,2BAAA;EACT,OAAA,EAAS,UAAU;AAAA;AAAA,KAGhB,4BAAA;EACH,KAAA;EACA,SAAS;AAAA;AAAA,KAGN,6BAAA;EACH,mBAAA,CAAoB,KAAA,EAAO,2BAAA,GAA8B,OAAA,CAAQ,4BAAA;AAAA;AAAA,KAG9D,uBAAA;EACH,OAAA,EAAS,2BAAA;EACT,KAAA;EACA,WAAA;IAAe,MAAA,IAAU,OAAO;EAAA;AAAA;AAAA,KAG7B,wBAAA;EACH,KAAA;EACA,SAAS;AAAA;AAAA,KAGN,yBAAA;EACH,eAAA,CAAgB,KAAA,EAAO,uBAAA,GAA0B,OAAA,CAAQ,wBAAA;AAAA;AAAA,KAGtD,iCAAA;EACH,OAAA,EAAS,2BAAA;EACT,KAAA;EACA,WAAA;IAAe,MAAA,IAAU,OAAO;EAAA;AAAA;AAAA,KAG7B,kCAAA;EACH,KAAA;EACA,MAAA;EACA,OAAA;EACA,SAAA;AAAA;AAAA,KAGG,mCAAA;EACH,yBAAA,CACE,KAAA,EAAO,iCAAA,GACN,OAAA,CAAQ,kCAAA;AAAA;;;cCpBP,OAAA,GAAW,IAAY;;AD3BsD;;;;;;;;;AAI9D;AAAA;;;;AAKV;AAAA;;cC2EL,eAAA,GACJ,MAAA,EAAQ,oBAAA;;;;;AAIR,oBAAA,IAAwB,IAAA,0BACvB,aAAa;;;;;;AD1FmE;;;;;;;;;AAI9D;AAAA;;;cEMf,mBAAA,GAAuB,SAAA,GAAY,OAAA,EAAS,aAAa;;;cCdzD,UAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;cAiBA,eAAA,EAAiB,aAAa,CAAC,SAAA;;;KCtBhC,6BAAA;EACH,UAAA;EACA,QAAA;IACE,MAAA;IACA,yBAAA;IACA,WAAA;IACA,eAAA;EAAA;AAAA;;;;AJOiB;AAAA;;;;AAKV;AAAA;;;;cIKL,sBAAA,GAA0B,KAAA,EAAO,6BAAA,KAAgC,kBAWrE;;;;;;AJzBiF;cKH7E,aAAA,EAAe,kBAGpB;;;;;;ALAkF;;;;YMDvE,iBAAA;IACR,GAAA,EAAK,oBAAoB;EAAA;AAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{logWarn as e}from"@usebutr/core";import{buildAccount as
|
|
1
|
+
import{logWarn as e,sanitizeIcon as t}from"@usebutr/core";import{buildAccount as n,discoverWalletStandard as r,getFeature as i,pickAccountByAddress as a,pickFirstAddress as o,slugify as s}from"@usebutr/wallet-standard-shared";const c=e=>({getBalance:!1,getTransactionReceipt:!1,requestAccounts:!1,sendTransaction:e.features.signAndExecuteTransaction,signIn:!1,signMessage:e.features.signMessage,signTransaction:e.features.signTransaction,subscribe:e.features.events,switchAccount:!1,switchChain:e.chainCount>1}),l=`sui:`,u=e=>{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.codePointAt(e)??0;return n},d=e=>s(`sui`,e),f=e=>e.chains.find(e=>e===`sui:mainnet`)||(e.chains.find(e=>e.startsWith(l))??null),p=(e,t)=>({id:e,name:t,namespace:`sui`,reference:e.slice(4)}),m=(e,t)=>n(e,t),h=e=>{if(typeof e==`string`||e&&typeof e==`object`&&`toJSON`in e&&typeof e.toJSON==`function`)return e;throw TypeError(`Sui sendTx/signTransaction expects a @mysten/sui Transaction (with toJSON()) or a base64-encoded string`)},g=(n,r)=>{let s=f(n);if(!s)return null;let g=i(n,`standard:connect`);if(!g)return null;let _=i(n,`standard:disconnect`),v=i(n,`standard:events`),y=i(n,`sui:signPersonalMessage`),b=i(n,`sui:signAndExecuteTransaction`),x=i(n,`sui:signTransaction`),S=s,C=()=>p(S,n.name),w=new Set,T=()=>{if(n.accounts.length===0)return;let e=C(),t=n.accounts.map(t=>m(t.address,e)),r=t[0];if(r)for(let e of w)e({account:r,accounts:t,type:`accountChanged`})};return r?.(()=>{for(let e of w)e({type:`disconnected`})}),{capabilities:c({chainCount:n.chains.filter(e=>e.startsWith(l)).length,features:{events:!!v,signAndExecuteTransaction:!!b,signMessage:!!y,signTransaction:!!x}}),chainPlatform:`sui`,async connect(e){await g.connect(e?.silent?{silent:!0}:void 0)},async disconnect(){if(_)try{await _.disconnect()}catch(t){e(`[butr] Sui Wallet Standard disconnect threw:`,t)}},getAccount(){let e=o(n.accounts);return e?Promise.resolve(m(e,C())):Promise.resolve(null)},getAccounts(){let e=C();return Promise.resolve(n.accounts.map(t=>m(t.address,e)))},getBalance(){return Promise.resolve({decimals:9,formatted:`0`,symbol:`SUI`,value:0n})},getSigner(){return Promise.resolve(n)},getTransactionReceipt(){return Promise.resolve({status:`Pending`})},icon:t(n.icon),id:d(n.name),name:n.name,async requestAccounts(){await g.connect()},async sendTx(e,t){if(!b)throw Error(`Wallet ${n.name} does not advertise sui:signAndExecuteTransaction`);let r=t?a(n.accounts,t.walletAddress):n.accounts[0]??null;if(!r)throw Error(`No connected account`);let i=h(e);return(await b.signAndExecuteTransaction({account:r,chain:S,transaction:i})).digest},sendTxToChain(e,t,n,r){return r?.(),this.sendTx(e,n)},async signMessage(e,t){if(!y)throw Error(`Wallet ${n.name} does not advertise sui:signPersonalMessage`);let r=t?a(n.accounts,t.walletAddress):n.accounts[0]??null;if(!r)throw Error(`No connected account`);let i=await y.signPersonalMessage({account:r,message:e});return{signature:u(i.signature),signedMessage:u(i.bytes)}},...x?{async signTransaction(e,t){let r=t?a(n.accounts,t.walletAddress):n.accounts[0]??null;if(!r)throw Error(`No connected account`);let i=h(e);return u((await x.signTransaction({account:r,chain:S,transaction:i})).bytes)}}:{},subscribe(e){w.add(e);let t=null;if(v){let n=v.on(`change`,t=>{if(t.chains){let e=t.chains.find(e=>e===`sui:mainnet`)??t.chains.find(e=>e.startsWith(l));e&&(S=e)}if(t.accounts){if(t.accounts.length===0){e({type:`disconnected`});return}let n=C(),r=t.accounts.map(e=>m(e.address,n)),i=r[0];if(!i)return;e({account:i,accounts:r,type:`accountChanged`});return}t.chains&&T()});t=()=>n()}return()=>{w.delete(e),t?.()}},switchChain(e){if(e.namespace!==`sui`)throw Error(`Sui adapter received non-Sui chain "${e.id}". Pass a chain with namespace "sui".`);if(!n.chains.includes(e.id))throw Error(`Wallet ${n.name} does not advertise chain "${e.id}". Available: ${n.chains.join(`, `)}`);return S=e.id,T(),Promise.resolve()}}},_=e=>r(e,(e,t)=>g(e,t)),v={devnet:{id:`sui:devnet`,name:`Sui Devnet`,namespace:`sui`,reference:`devnet`},localnet:{id:`sui:localnet`,name:`Sui Localnet`,namespace:`sui`,reference:`localnet`},mainnet:{id:`sui:mainnet`,name:`Sui Mainnet`,namespace:`sui`,reference:`mainnet`},testnet:{id:`sui:testnet`,name:`Sui Testnet`,namespace:`sui`,reference:`testnet`}},y=Object.values(v),b={platform:`sui`,subscribe:_};export{v as SUI_CHAINS,y as SUI_CHAINS_LIST,g as buildSuiAdapter,_ as discoverSuiAdapters,c as resolveSuiCapabilities,d as slugify,b as suiDiscoverer};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["kitSlugify"],"sources":["../src/capabilities.ts","../src/wallet-standard-adapter.ts","../src/wallet-standard.ts","../src/chains.ts","../src/discoverer.ts"],"sourcesContent":["import type { WalletCapabilities } from \"@usebutr/core\";\n\ntype WalletStandardCapabilityInput = {\n chainCount: number;\n features: {\n events: boolean;\n signAndExecuteTransaction: boolean;\n signMessage: boolean;\n signTransaction: boolean;\n };\n};\n\n/**\n * Sui Wallet Standard capability mapping. Mirrors the SVM resolver:\n * butr ships no RPC, so balance/receipt always false.\n *\n * - `sendTransaction = sui:signAndExecuteTransaction present`. The wallet\n * broadcasts; consumers receive the digest.\n * - `signTransaction = sui:signTransaction present`. Sign-only; consumers\n * broadcast with their own RPC client (`@mysten/sui`'s SuiClient).\n * - `signMessage = sui:signPersonalMessage present`.\n * - `signIn = false`. Sui has no SIWS-equivalent feature in Wallet Standard.\n * - `switchChain = chainCount > 1`. Same posture as SVM — local re-routing\n * for `signAndExecuteTransaction`'s per-call `chain` input.\n */\nconst resolveSuiCapabilities = (input: WalletStandardCapabilityInput): WalletCapabilities => ({\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: false,\n sendTransaction: input.features.signAndExecuteTransaction,\n signIn: false,\n signMessage: input.features.signMessage,\n signTransaction: input.features.signTransaction,\n subscribe: input.features.events,\n switchAccount: false,\n switchChain: input.chainCount > 1,\n});\n\nexport type { WalletStandardCapabilityInput };\nexport { resolveSuiCapabilities };\n","import type { Account, ChainBase, ConnectorEvent, WalletAdapter } from \"@usebutr/core\";\nimport { logWarn } from \"@usebutr/core\";\nimport {\n buildAccount,\n getFeature,\n pickAccountByAddress,\n pickFirstAddress,\n slugify as kitSlugify,\n} from \"@usebutr/wallet-standard-shared\";\nimport type {\n StandardConnectFeature,\n StandardDisconnectFeature,\n StandardEventsFeature,\n WalletStandardWallet,\n} from \"@usebutr/wallet-standard-shared\";\n\nimport { resolveSuiCapabilities } from \"./capabilities\";\nimport type {\n SuiSignAndExecuteTransactionFeature,\n SuiSignPersonalMessageFeature,\n SuiSignTransactionFeature,\n} from \"./wallet-standard-types\";\n\nconst SUI_PREFIX = \"sui:\";\nconst SUI_DECIMALS = 9;\n\n/** Cross-platform base64 → Uint8Array. Sui's Wallet Standard features\n * return base64 strings (`bytes`, `signature`), while butr's\n * `Wallet.signMessage` contract is Uint8Array. */\nconst base64ToBytes = (b64: string): Uint8Array => {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n out[i] = binary.codePointAt(i) ?? 0;\n }\n return out;\n};\n\nconst slugify = (name: string): string => kitSlugify(\"sui\", name);\n\nconst pickSuiChain = (wallet: WalletStandardWallet): string | null => {\n const mainnet = wallet.chains.find((c) => c === \"sui:mainnet\");\n if (mainnet) {\n return mainnet;\n }\n return wallet.chains.find((c) => c.startsWith(SUI_PREFIX)) ?? null;\n};\n\nconst buildSuiChain = (chainId: string, walletName: string): ChainBase => ({\n id: chainId,\n // Same posture as SVM: butr ships no chain-id → name table. Consumers\n // overlay via structural typing.\n name: walletName,\n namespace: \"sui\",\n reference: chainId.slice(SUI_PREFIX.length),\n});\n\nconst buildSuiAccount = (address: string, chain: ChainBase): Account =>\n buildAccount(address, chain);\n\n/** Coerce butr's `unknown` tx into the shape `sui:signAndExecuteTransaction`\n * expects (an object with `toJSON()` returning a Promise<string>). When\n * consumers pass a base64 string directly, we wrap it in a stub object so\n * the feature contract stays satisfied without us depending on\n * `@mysten/sui`. */\nconst coerceSuiTransaction = (tx: unknown): { toJSON(): Promise<string> } | string => {\n if (typeof tx === \"string\") {\n return tx;\n }\n if (tx && typeof tx === \"object\" && \"toJSON\" in tx && typeof tx.toJSON === \"function\") {\n return tx as { toJSON(): Promise<string> };\n }\n throw new TypeError(\n \"Sui sendTx/signTransaction expects a @mysten/sui Transaction (with toJSON()) or a base64-encoded string\",\n );\n};\n\n/**\n * Adapt a Sui Wallet Standard `Wallet` into a butr `WalletAdapter`.\n *\n * Returns `null` if the wallet doesn't advertise any Sui chain or doesn't\n * expose `standard:connect`. Same posture as `buildSvmAdapter`: gate\n * features on what each wallet advertises, return placeholders for\n * RPC-backed reads (`getBalance`, `getTransactionReceipt`), forward\n * `subscribe` through `standard:events`.\n *\n * **Known limitations**\n *\n * - `getBalance` returns a `{ value: 0n, symbol: \"SUI\" }` placeholder.\n * Consumers wrap `@mysten/sui`'s `SuiClient` for real reads.\n * - `getTransactionReceipt` returns `\"Pending\"` for the same reason.\n * - `switchChain` is local-state-only (mirrors SVM). Sui Wallet Standard\n * has no \"tell the wallet to switch network\" RPC; the wallet's UI\n * controls its global cluster setting.\n */\nconst buildSuiAdapter = (\n wallet: WalletStandardWallet,\n /** Optional. Called with a function that pushes a synthetic\n * `disconnected` event to all current subscribers. The discovery\n * layer invokes it on Wallet Standard `unregister`. */\n registerDisconnector?: (emit: () => void) => void,\n): WalletAdapter | null => {\n const suiChainId = pickSuiChain(wallet);\n if (!suiChainId) {\n return null;\n }\n const connect = getFeature<StandardConnectFeature>(wallet, \"standard:connect\");\n if (!connect) {\n return null;\n }\n\n const disconnect = getFeature<StandardDisconnectFeature>(wallet, \"standard:disconnect\");\n const events = getFeature<StandardEventsFeature>(wallet, \"standard:events\");\n const signMessage = getFeature<SuiSignPersonalMessageFeature>(wallet, \"sui:signPersonalMessage\");\n const signAndExecute = getFeature<SuiSignAndExecuteTransactionFeature>(\n wallet,\n \"sui:signAndExecuteTransaction\",\n );\n const signTx = getFeature<SuiSignTransactionFeature>(wallet, \"sui:signTransaction\");\n\n let currentChainId = suiChainId;\n const currentChain = (): ChainBase => buildSuiChain(currentChainId, wallet.name);\n\n const listeners = new Set<(event: ConnectorEvent) => void>();\n const notifyAccountChanged = () => {\n if (wallet.accounts.length === 0) {\n return;\n }\n const chain = currentChain();\n const built = wallet.accounts.map((a) => buildSuiAccount(a.address, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n for (const listener of listeners) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n };\n\n registerDisconnector?.(() => {\n for (const listener of listeners) {\n listener({ type: \"disconnected\" });\n }\n });\n\n return {\n capabilities: resolveSuiCapabilities({\n chainCount: wallet.chains.filter((c) => c.startsWith(SUI_PREFIX)).length,\n features: {\n events: Boolean(events),\n signAndExecuteTransaction: Boolean(signAndExecute),\n signMessage: Boolean(signMessage),\n signTransaction: Boolean(signTx),\n },\n }),\n chainPlatform: \"sui\",\n\n async connect(opts) {\n await connect.connect(opts?.silent ? { silent: true } : undefined);\n },\n\n async disconnect() {\n if (disconnect) {\n try {\n await disconnect.disconnect();\n } catch (error) {\n logWarn(\"[butr] Sui Wallet Standard disconnect threw:\", error);\n }\n }\n },\n\n getAccount() {\n const address = pickFirstAddress(wallet.accounts);\n if (!address) {\n return Promise.resolve(null);\n }\n return Promise.resolve(buildSuiAccount(address, currentChain()));\n },\n\n getAccounts() {\n const chain = currentChain();\n return Promise.resolve(wallet.accounts.map((a) => buildSuiAccount(a.address, chain)));\n },\n\n getBalance() {\n return Promise.resolve({\n decimals: SUI_DECIMALS,\n formatted: \"0\",\n symbol: \"SUI\",\n value: 0n,\n });\n },\n\n getSigner() {\n return Promise.resolve(wallet);\n },\n\n getTransactionReceipt() {\n return Promise.resolve({ status: \"Pending\" as const });\n },\n\n icon: wallet.icon,\n id: slugify(wallet.name),\n name: wallet.name,\n\n async requestAccounts() {\n await connect.connect();\n },\n\n async sendTx(tx, account) {\n if (!signAndExecute) {\n throw new Error(`Wallet ${wallet.name} does not advertise sui:signAndExecuteTransaction`);\n }\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const transaction = coerceSuiTransaction(tx);\n const output = await signAndExecute.signAndExecuteTransaction({\n account: wsAccount,\n chain: currentChainId,\n transaction,\n });\n return output.digest;\n },\n\n sendTxToChain(tx, _targetChainId, account, cb) {\n cb?.();\n return this.sendTx(tx, account);\n },\n\n async signMessage(msg, account) {\n if (!signMessage) {\n throw new Error(`Wallet ${wallet.name} does not advertise sui:signPersonalMessage`);\n }\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const output = await signMessage.signPersonalMessage({\n account: wsAccount,\n message: msg,\n });\n return {\n signature: base64ToBytes(output.signature),\n signedMessage: base64ToBytes(output.bytes),\n };\n },\n\n ...(signTx\n ? {\n async signTransaction(tx, account) {\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const transaction = coerceSuiTransaction(tx);\n const output = await signTx.signTransaction({\n account: wsAccount,\n chain: currentChainId,\n transaction,\n });\n return base64ToBytes(output.bytes);\n },\n }\n : {}),\n\n subscribe(listener) {\n listeners.add(listener);\n let unsubWallet: (() => void) | null = null;\n if (events) {\n const unsub = events.on(\"change\", (changes) => {\n if (changes.chains) {\n const next =\n changes.chains.find((c) => c === \"sui:mainnet\") ??\n changes.chains.find((c) => c.startsWith(SUI_PREFIX));\n if (next) {\n currentChainId = next;\n }\n }\n\n if (changes.accounts) {\n if (changes.accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const chain = currentChain();\n const built = changes.accounts.map((a) => buildSuiAccount(a.address, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n return;\n }\n\n if (changes.chains) {\n notifyAccountChanged();\n }\n });\n unsubWallet = () => unsub();\n }\n return () => {\n listeners.delete(listener);\n unsubWallet?.();\n };\n },\n\n switchChain(chain) {\n if (chain.namespace !== \"sui\") {\n throw new Error(\n `Sui adapter received non-Sui chain \"${chain.id}\". Pass a chain with namespace \"sui\".`,\n );\n }\n if (!wallet.chains.includes(chain.id)) {\n throw new Error(\n `Wallet ${wallet.name} does not advertise chain \"${chain.id}\". Available: ${wallet.chains.join(\", \")}`,\n );\n }\n currentChainId = chain.id;\n notifyAccountChanged();\n return Promise.resolve();\n },\n };\n};\n\nexport { buildSuiAdapter, slugify };\n","import type { WalletAdapter } from \"@usebutr/core\";\nimport { discoverWalletStandard } from \"@usebutr/wallet-standard-shared\";\n\nimport { buildSuiAdapter } from \"./wallet-standard-adapter\";\n\n/**\n * Subscribe to Sui Wallet Standard announcements.\n * Spec: https://docs.sui.io/standards/wallet-standard\n *\n * Runtime requires the `@wallet-standard/app` package, which is an\n * **optional peer dependency** of butr.\n *\n * Sui wallets share the same `getWallets()` bus as SVM wallets — Phantom\n * advertises features for SVM, Sui, and Bitcoin from a single Wallet\n * Standard wallet object. `buildSuiAdapter` returns `null` for wallets\n * that don't advertise any `sui:*` features, so we cleanly end up with\n * one adapter per platform on multi-chain wallets.\n *\n * The discovery loop (dynamic import, dedupe, register / unregister\n * bridge) lives in `@usebutr/wallet-standard-shared`.\n */\nconst discoverSuiAdapters = (onAdapter: (adapter: WalletAdapter) => void): (() => void) =>\n discoverWalletStandard(onAdapter, (wallet, registerDisconnector) =>\n buildSuiAdapter(wallet, registerDisconnector),\n );\n\nexport { discoverSuiAdapters };\n","import type { ChainBase } from \"@usebutr/core\";\n\n// Sui wallets follow the Wallet Standard convention of advertising\n// chains as `sui:mainnet` / `sui:testnet` / `sui:devnet` / `sui:localnet`\n// rather than the strict CAIP-2 form (the genesis-checkpoint hash).\n// Sui Wallet, Suiet, Phantom (Sui), and Surf all exchange these short\n// names; the adapter's `switchChain` rejects anything else.\nconst SUI_CHAINS = {\n devnet: { id: \"sui:devnet\", name: \"Sui Devnet\", namespace: \"sui\", reference: \"devnet\" },\n localnet: {\n id: \"sui:localnet\",\n name: \"Sui Localnet\",\n namespace: \"sui\",\n reference: \"localnet\",\n },\n mainnet: {\n id: \"sui:mainnet\",\n name: \"Sui Mainnet\",\n namespace: \"sui\",\n reference: \"mainnet\",\n },\n testnet: { id: \"sui:testnet\", name: \"Sui Testnet\", namespace: \"sui\", reference: \"testnet\" },\n} as const satisfies Record<string, ChainBase>;\n\nconst SUI_CHAINS_LIST: ReadonlyArray<ChainBase> = Object.values(SUI_CHAINS);\n\nexport { SUI_CHAINS, SUI_CHAINS_LIST };\n","import type { PlatformDiscoverer } from \"@usebutr/core\";\n\nimport { discoverSuiAdapters } from \"./wallet-standard\";\n\n/**\n * Sui's `PlatformDiscoverer`: Sui Wallet Standard announcements. No\n * legacy fallback — Sui standardised on Wallet Standard from launch.\n */\nconst suiDiscoverer: PlatformDiscoverer = {\n platform: \"sui\",\n subscribe: discoverSuiAdapters,\n};\n\nexport { suiDiscoverer };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["kitSlugify"],"sources":["../src/capabilities.ts","../src/wallet-standard-adapter.ts","../src/wallet-standard.ts","../src/chains.ts","../src/discoverer.ts"],"sourcesContent":["import type { WalletCapabilities } from \"@usebutr/core\";\n\ntype WalletStandardCapabilityInput = {\n chainCount: number;\n features: {\n events: boolean;\n signAndExecuteTransaction: boolean;\n signMessage: boolean;\n signTransaction: boolean;\n };\n};\n\n/**\n * Sui Wallet Standard capability mapping. Mirrors the SVM resolver:\n * butr ships no RPC, so balance/receipt always false.\n *\n * - `sendTransaction = sui:signAndExecuteTransaction present`. The wallet\n * broadcasts; consumers receive the digest.\n * - `signTransaction = sui:signTransaction present`. Sign-only; consumers\n * broadcast with their own RPC client (`@mysten/sui`'s SuiClient).\n * - `signMessage = sui:signPersonalMessage present`.\n * - `signIn = false`. Sui has no SIWS-equivalent feature in Wallet Standard.\n * - `switchChain = chainCount > 1`. Same posture as SVM — local re-routing\n * for `signAndExecuteTransaction`'s per-call `chain` input.\n */\nconst resolveSuiCapabilities = (input: WalletStandardCapabilityInput): WalletCapabilities => ({\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: false,\n sendTransaction: input.features.signAndExecuteTransaction,\n signIn: false,\n signMessage: input.features.signMessage,\n signTransaction: input.features.signTransaction,\n subscribe: input.features.events,\n switchAccount: false,\n switchChain: input.chainCount > 1,\n});\n\nexport type { WalletStandardCapabilityInput };\nexport { resolveSuiCapabilities };\n","import type { Account, ChainBase, ConnectorEvent, WalletAdapter } from \"@usebutr/core\";\nimport { logWarn, sanitizeIcon } from \"@usebutr/core\";\nimport {\n buildAccount,\n getFeature,\n pickAccountByAddress,\n pickFirstAddress,\n slugify as kitSlugify,\n} from \"@usebutr/wallet-standard-shared\";\nimport type {\n StandardConnectFeature,\n StandardDisconnectFeature,\n StandardEventsFeature,\n WalletStandardWallet,\n} from \"@usebutr/wallet-standard-shared\";\n\nimport { resolveSuiCapabilities } from \"./capabilities\";\nimport type {\n SuiSignAndExecuteTransactionFeature,\n SuiSignPersonalMessageFeature,\n SuiSignTransactionFeature,\n} from \"./wallet-standard-types\";\n\nconst SUI_PREFIX = \"sui:\";\nconst SUI_DECIMALS = 9;\n\n/** Cross-platform base64 → Uint8Array. Sui's Wallet Standard features\n * return base64 strings (`bytes`, `signature`), while butr's\n * `Wallet.signMessage` contract is Uint8Array. */\nconst base64ToBytes = (b64: string): Uint8Array => {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n out[i] = binary.codePointAt(i) ?? 0;\n }\n return out;\n};\n\nconst slugify = (name: string): string => kitSlugify(\"sui\", name);\n\nconst pickSuiChain = (wallet: WalletStandardWallet): string | null => {\n const mainnet = wallet.chains.find((c) => c === \"sui:mainnet\");\n if (mainnet) {\n return mainnet;\n }\n return wallet.chains.find((c) => c.startsWith(SUI_PREFIX)) ?? null;\n};\n\nconst buildSuiChain = (chainId: string, walletName: string): ChainBase => ({\n id: chainId,\n // Same posture as SVM: butr ships no chain-id → name table. Consumers\n // overlay via structural typing.\n name: walletName,\n namespace: \"sui\",\n reference: chainId.slice(SUI_PREFIX.length),\n});\n\nconst buildSuiAccount = (address: string, chain: ChainBase): Account =>\n buildAccount(address, chain);\n\n/** Coerce butr's `unknown` tx into the shape `sui:signAndExecuteTransaction`\n * expects (an object with `toJSON()` returning a Promise<string>). When\n * consumers pass a base64 string directly, we wrap it in a stub object so\n * the feature contract stays satisfied without us depending on\n * `@mysten/sui`. */\nconst coerceSuiTransaction = (tx: unknown): { toJSON(): Promise<string> } | string => {\n if (typeof tx === \"string\") {\n return tx;\n }\n if (tx && typeof tx === \"object\" && \"toJSON\" in tx && typeof tx.toJSON === \"function\") {\n return tx as { toJSON(): Promise<string> };\n }\n throw new TypeError(\n \"Sui sendTx/signTransaction expects a @mysten/sui Transaction (with toJSON()) or a base64-encoded string\",\n );\n};\n\n/**\n * Adapt a Sui Wallet Standard `Wallet` into a butr `WalletAdapter`.\n *\n * Returns `null` if the wallet doesn't advertise any Sui chain or doesn't\n * expose `standard:connect`. Same posture as `buildSvmAdapter`: gate\n * features on what each wallet advertises, return placeholders for\n * RPC-backed reads (`getBalance`, `getTransactionReceipt`), forward\n * `subscribe` through `standard:events`.\n *\n * **Known limitations**\n *\n * - `getBalance` returns a `{ value: 0n, symbol: \"SUI\" }` placeholder.\n * Consumers wrap `@mysten/sui`'s `SuiClient` for real reads.\n * - `getTransactionReceipt` returns `\"Pending\"` for the same reason.\n * - `switchChain` is local-state-only (mirrors SVM). Sui Wallet Standard\n * has no \"tell the wallet to switch network\" RPC; the wallet's UI\n * controls its global cluster setting.\n */\nconst buildSuiAdapter = (\n wallet: WalletStandardWallet,\n /** Optional. Called with a function that pushes a synthetic\n * `disconnected` event to all current subscribers. The discovery\n * layer invokes it on Wallet Standard `unregister`. */\n registerDisconnector?: (emit: () => void) => void,\n): WalletAdapter | null => {\n const suiChainId = pickSuiChain(wallet);\n if (!suiChainId) {\n return null;\n }\n const connect = getFeature<StandardConnectFeature>(wallet, \"standard:connect\");\n if (!connect) {\n return null;\n }\n\n const disconnect = getFeature<StandardDisconnectFeature>(wallet, \"standard:disconnect\");\n const events = getFeature<StandardEventsFeature>(wallet, \"standard:events\");\n const signMessage = getFeature<SuiSignPersonalMessageFeature>(wallet, \"sui:signPersonalMessage\");\n const signAndExecute = getFeature<SuiSignAndExecuteTransactionFeature>(\n wallet,\n \"sui:signAndExecuteTransaction\",\n );\n const signTx = getFeature<SuiSignTransactionFeature>(wallet, \"sui:signTransaction\");\n\n let currentChainId = suiChainId;\n const currentChain = (): ChainBase => buildSuiChain(currentChainId, wallet.name);\n\n const listeners = new Set<(event: ConnectorEvent) => void>();\n const notifyAccountChanged = () => {\n if (wallet.accounts.length === 0) {\n return;\n }\n const chain = currentChain();\n const built = wallet.accounts.map((a) => buildSuiAccount(a.address, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n for (const listener of listeners) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n };\n\n registerDisconnector?.(() => {\n for (const listener of listeners) {\n listener({ type: \"disconnected\" });\n }\n });\n\n return {\n capabilities: resolveSuiCapabilities({\n chainCount: wallet.chains.filter((c) => c.startsWith(SUI_PREFIX)).length,\n features: {\n events: Boolean(events),\n signAndExecuteTransaction: Boolean(signAndExecute),\n signMessage: Boolean(signMessage),\n signTransaction: Boolean(signTx),\n },\n }),\n chainPlatform: \"sui\",\n\n async connect(opts) {\n await connect.connect(opts?.silent ? { silent: true } : undefined);\n },\n\n async disconnect() {\n if (disconnect) {\n try {\n await disconnect.disconnect();\n } catch (error) {\n logWarn(\"[butr] Sui Wallet Standard disconnect threw:\", error);\n }\n }\n },\n\n getAccount() {\n const address = pickFirstAddress(wallet.accounts);\n if (!address) {\n return Promise.resolve(null);\n }\n return Promise.resolve(buildSuiAccount(address, currentChain()));\n },\n\n getAccounts() {\n const chain = currentChain();\n return Promise.resolve(wallet.accounts.map((a) => buildSuiAccount(a.address, chain)));\n },\n\n getBalance() {\n return Promise.resolve({\n decimals: SUI_DECIMALS,\n formatted: \"0\",\n symbol: \"SUI\",\n value: 0n,\n });\n },\n\n getSigner() {\n return Promise.resolve(wallet);\n },\n\n getTransactionReceipt() {\n return Promise.resolve({ status: \"Pending\" as const });\n },\n\n icon: sanitizeIcon(wallet.icon),\n id: slugify(wallet.name),\n name: wallet.name,\n\n async requestAccounts() {\n await connect.connect();\n },\n\n async sendTx(tx, account) {\n if (!signAndExecute) {\n throw new Error(`Wallet ${wallet.name} does not advertise sui:signAndExecuteTransaction`);\n }\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const transaction = coerceSuiTransaction(tx);\n const output = await signAndExecute.signAndExecuteTransaction({\n account: wsAccount,\n chain: currentChainId,\n transaction,\n });\n return output.digest;\n },\n\n sendTxToChain(tx, _targetChainId, account, cb) {\n cb?.();\n return this.sendTx(tx, account);\n },\n\n async signMessage(msg, account) {\n if (!signMessage) {\n throw new Error(`Wallet ${wallet.name} does not advertise sui:signPersonalMessage`);\n }\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const output = await signMessage.signPersonalMessage({\n account: wsAccount,\n message: msg,\n });\n return {\n signature: base64ToBytes(output.signature),\n signedMessage: base64ToBytes(output.bytes),\n };\n },\n\n ...(signTx\n ? {\n async signTransaction(tx, account) {\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const transaction = coerceSuiTransaction(tx);\n const output = await signTx.signTransaction({\n account: wsAccount,\n chain: currentChainId,\n transaction,\n });\n return base64ToBytes(output.bytes);\n },\n }\n : {}),\n\n subscribe(listener) {\n listeners.add(listener);\n let unsubWallet: (() => void) | null = null;\n if (events) {\n const unsub = events.on(\"change\", (changes) => {\n if (changes.chains) {\n const next =\n changes.chains.find((c) => c === \"sui:mainnet\") ??\n changes.chains.find((c) => c.startsWith(SUI_PREFIX));\n if (next) {\n currentChainId = next;\n }\n }\n\n if (changes.accounts) {\n if (changes.accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const chain = currentChain();\n const built = changes.accounts.map((a) => buildSuiAccount(a.address, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n return;\n }\n\n if (changes.chains) {\n notifyAccountChanged();\n }\n });\n unsubWallet = () => unsub();\n }\n return () => {\n listeners.delete(listener);\n unsubWallet?.();\n };\n },\n\n switchChain(chain) {\n if (chain.namespace !== \"sui\") {\n throw new Error(\n `Sui adapter received non-Sui chain \"${chain.id}\". Pass a chain with namespace \"sui\".`,\n );\n }\n if (!wallet.chains.includes(chain.id)) {\n throw new Error(\n `Wallet ${wallet.name} does not advertise chain \"${chain.id}\". Available: ${wallet.chains.join(\", \")}`,\n );\n }\n currentChainId = chain.id;\n notifyAccountChanged();\n return Promise.resolve();\n },\n };\n};\n\nexport { buildSuiAdapter, slugify };\n","import type { WalletAdapter } from \"@usebutr/core\";\nimport { discoverWalletStandard } from \"@usebutr/wallet-standard-shared\";\n\nimport { buildSuiAdapter } from \"./wallet-standard-adapter\";\n\n/**\n * Subscribe to Sui Wallet Standard announcements.\n * Spec: https://docs.sui.io/standards/wallet-standard\n *\n * Runtime requires the `@wallet-standard/app` package, which is an\n * **optional peer dependency** of butr.\n *\n * Sui wallets share the same `getWallets()` bus as SVM wallets — Phantom\n * advertises features for SVM, Sui, and Bitcoin from a single Wallet\n * Standard wallet object. `buildSuiAdapter` returns `null` for wallets\n * that don't advertise any `sui:*` features, so we cleanly end up with\n * one adapter per platform on multi-chain wallets.\n *\n * The discovery loop (dynamic import, dedupe, register / unregister\n * bridge) lives in `@usebutr/wallet-standard-shared`.\n */\nconst discoverSuiAdapters = (onAdapter: (adapter: WalletAdapter) => void): (() => void) =>\n discoverWalletStandard(onAdapter, (wallet, registerDisconnector) =>\n buildSuiAdapter(wallet, registerDisconnector),\n );\n\nexport { discoverSuiAdapters };\n","import type { ChainBase } from \"@usebutr/core\";\n\n// Sui wallets follow the Wallet Standard convention of advertising\n// chains as `sui:mainnet` / `sui:testnet` / `sui:devnet` / `sui:localnet`\n// rather than the strict CAIP-2 form (the genesis-checkpoint hash).\n// Sui Wallet, Suiet, Phantom (Sui), and Surf all exchange these short\n// names; the adapter's `switchChain` rejects anything else.\nconst SUI_CHAINS = {\n devnet: { id: \"sui:devnet\", name: \"Sui Devnet\", namespace: \"sui\", reference: \"devnet\" },\n localnet: {\n id: \"sui:localnet\",\n name: \"Sui Localnet\",\n namespace: \"sui\",\n reference: \"localnet\",\n },\n mainnet: {\n id: \"sui:mainnet\",\n name: \"Sui Mainnet\",\n namespace: \"sui\",\n reference: \"mainnet\",\n },\n testnet: { id: \"sui:testnet\", name: \"Sui Testnet\", namespace: \"sui\", reference: \"testnet\" },\n} as const satisfies Record<string, ChainBase>;\n\nconst SUI_CHAINS_LIST: ReadonlyArray<ChainBase> = Object.values(SUI_CHAINS);\n\nexport { SUI_CHAINS, SUI_CHAINS_LIST };\n","import type { PlatformDiscoverer } from \"@usebutr/core\";\n\nimport { discoverSuiAdapters } from \"./wallet-standard\";\n\n/**\n * Sui's `PlatformDiscoverer`: Sui Wallet Standard announcements. No\n * legacy fallback — Sui standardised on Wallet Standard from launch.\n */\nconst suiDiscoverer: PlatformDiscoverer = {\n platform: \"sui\",\n subscribe: discoverSuiAdapters,\n};\n\nexport { suiDiscoverer };\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebutr/sui",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Wallet Standard adapter for butr (Sui).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Pedro Filho <pedro@filho.me>",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@usebutr/core": "0.1
|
|
29
|
-
"@usebutr/wallet-standard-shared": "0.1
|
|
28
|
+
"@usebutr/core": "0.2.1",
|
|
29
|
+
"@usebutr/wallet-standard-shared": "0.2.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@wallet-standard/app": "^1.1.0",
|