# Yours Wallet Provider API - LLM Reference ## Quick Reference **Core Object**: `window.yours` (injected by browser extension) **React Hook**: `useYoursWallet()` from `yours-wallet-provider` **Installation**: `npm i yours-wallet-provider` ### Essential Methods ```javascript // Connection await wallet.connect() → string (identityPubKey) await wallet.disconnect() → boolean await wallet.isConnected() → boolean // Core Data await wallet.getAddresses() → {bsvAddress, ordAddress, identityAddress} await wallet.getPubKeys() → {bsvPubKey, ordPubKey, identityPubKey} await wallet.getBalance() → {bsv, satoshis, usdInCents} // Transactions await wallet.sendBsv(SendBsv[]) → {txid, rawtx} await wallet.sendBsv20(SendBsv20) → {txid, rawtx} await wallet.transferOrdinal(TransferOrdinal) → txid ``` ## Method Summary Table | Category | Method | Parameters | Returns | Purpose | |----------|---------|------------|---------|---------| | **Connection** | `connect()` | none | `string` | Connect wallet, get identity pubkey | | | `disconnect()` | none | `boolean` | Disconnect wallet | | | `isConnected()` | none | `boolean` | Check connection status | | **Wallet Info** | `getAddresses()` | none | `Addresses` | Get BSV/Ord/Identity addresses | | | `getPubKeys()` | none | `PubKeys` | Get public keys | | | `getBalance()` | none | `Balance` | Get BSV balance | | | `getExchangeRate()` | none | `number` | Get BSV/USD rate | | | `getPaymentUtxos()` | none | `Utxo[]` | Get spendable UTXOs | | | `getSocialProfile()` | none | `SocialProfile` | Get display name/avatar | | **Transactions** | `sendBsv()` | `SendBsv[]` | `SendBsvResponse` | Send BSV transactions | | | `broadcast()` | `Broadcast` | `string` | Broadcast raw transaction | | **Ordinals** | `inscribe()` | `InscribeRequest[]` | `SendBsvResponse` | Create inscriptions | | | `getOrdinals()` | `GetPaginatedOrdinals?` | `Ordinal[]` | Get user's ordinals | | | `transferOrdinal()` | `TransferOrdinal` | `string` | Transfer ordinal | | | `purchaseOrdinal()` | `PurchaseOrdinal` | `string` | Buy ordinal from marketplace | | **BSV-20** | `getBsv20s()` | none | `Bsv20[]` | Get BSV-20 tokens | | | `sendBsv20()` | `SendBsv20` | `SendBsv20Response` | Send BSV-20 tokens | | | `purchaseBsv20()` | `PurchaseOrdinal` | `string` | Buy BSV-20 from marketplace | | **MNEE** | `getMNEEBalance()` | none | `MNEEBalance` | Get MNEE balance | | | `sendMNEE()` | `SendMNEE[]` | `SendMNEEResponse` | Send MNEE stablecoin | | **Cryptography** | `signMessage()` | `SignMessage` | `SignedMessage` | Sign message | | | `getSignatures()` | `GetSignatures` | `SignatureResponse[]` | Get tx signatures | | | `encrypt()` | `EncryptRequest` | `string[]` | Encrypt data | | | `decrypt()` | `DecryptRequest` | `string[]` | Decrypt data | | **Advanced** | `generateTaggedKeys()` | `TaggedDerivationRequest` | `TaggedDerivationResponse` | Create tagged key pair | | | `getTaggedKeys()` | `GetTaggedKeysRequest` | `TaggedDerivationResponse[]` | Get existing tagged keys | | | `lock()` | `LockRequest[]` | `SendBsvResponse` | Time-lock BSV | | **Events** | `on()` | `event, listener` | `void` | Add event listener | | | `removeListener()` | `event, listener` | `void` | Remove event listener | ## Common Workflows ### 1. Basic Wallet Integration ```javascript // React setup import { YoursProvider, useYoursWallet } from 'yours-wallet-provider'; // App wrapper // Component usage const wallet = useYoursWallet(); // Check if installed if (!wallet?.isReady) { window.open("https://yours.org", "_blank"); return; } // Connect const pubKey = await wallet.connect(); // Event listeners (required for good UX) wallet.on('switchAccount', handleAccountSwitch); wallet.on('signedOut', () => wallet.disconnect()); ``` ### 2. Send BSV Transaction ```javascript const payments = [ { satoshis: 10000, address: "1ABC..." }, // Simple payment { satoshis: 5000, paymail: "user@domain.com" }, // Paymail { satoshis: 0, data: ["hello"].map(s => Buffer.from(s).toString('hex')) }, // Data { satoshis: 1, script: "76a914...88ac" } // Custom script ]; const { txid, rawtx } = await wallet.sendBsv(payments); ``` ### 3. Create Inscription ```javascript const inscriptions = [{ address: await wallet.getAddresses().ordAddress, base64Data: btoa("Hello World"), mimeType: "text/plain", map: { app: "MyApp", type: "text" }, satoshis: 1 }]; const { txid } = await wallet.inscribe(inscriptions); ``` ### 4. Paginated Ordinals Loading ```javascript let from = undefined; const allOrdinals = []; do { const { ordinals, from: nextFrom } = await wallet.getOrdinals({ from, limit: 50 }); allOrdinals.push(...ordinals); from = nextFrom; } while (from); ``` ## Complete Type Definitions ### Core Response Types ```typescript type Addresses = { bsvAddress: string; // For BSV transactions ordAddress: string; // For ordinals/inscriptions identityAddress: string; // For identity/social features }; type PubKeys = { bsvPubKey: string; ordPubKey: string; identityPubKey: string; }; type Balance = { bsv: number; // BSV amount (decimal) satoshis: number; // Satoshis (integer) usdInCents: number; // USD value in cents }; type MNEEBalance = { amount: number; decimalAmount: number; }; type SocialProfile = { displayName: string; avatar: string; }; type Utxo = { satoshis: number; script: string; // hex string txid: string; vout: number; }; ``` ### Transaction Types ```typescript type SendBsv = { address?: string; // Bitcoin address paymail?: string; // Paymail address satoshis: number; // Amount in satoshis data?: string[]; // Hex-encoded data array script?: string; // Custom output script (hex) inscription?: RawInscription; // Inscription data }; type SendBsv20 = { idOrTick: string; // Token ID or ticker address: string; // Recipient address amount: number; // Amount (wallet handles decimals) }; type SendMNEE = { address: string; amount: number; }; type TransferOrdinal = { address: string; // Recipient address origin: string; // Ordinal origin outpoint: string; // UTXO outpoint }; type PurchaseOrdinal = { outpoint: string; marketplaceRate?: number; marketplaceAddress?: string; }; ``` ### Response Types ```typescript type SendBsvResponse = { txid: string; rawtx: string; }; type SendBsv20Response = { txid: string; rawtx: string; }; type SendMNEEResponse = { txid: string; rawtx: string; }; type SignedMessage = { address: string; pubKey: string; sig: string; message: string; derivationTag: DerivationTag; }; ``` ### Ordinals & BSV-20 Types ```typescript type Ordinal = { txid: string; vout: number; outpoint: string; satoshis: number; owner?: string; script?: string; spend?: string; origin?: Origin; height: number; idx: number; data: OrdinalData; }; type GetPaginatedOrdinals = { from?: string; // pagination cursor limit?: number; // default: 50 mimeType?: string; // filter by content type }; type PaginatedOrdinalsResponse = { ordinals: Ordinal[]; from?: string; // undefined = no more results }; type Origin = { outpoint: string; nonce?: number; data?: OrdinalData; num?: string; map?: { [key: string]: any }; }; type OrdinalData = { types?: string[]; insc?: Inscription; map?: { [key: string]: any }; b?: File; sigma?: Sigma[]; list?: Listing; bsv20?: Bsv20; lock?: Lock; }; interface Bsv20 { p: string; op: string; dec: number; amt: string; all: Bsv20Balance; listed: Bsv20Balance; status?: Bsv20Status; tick?: string; icon?: string; id?: string; sym?: string; } interface Bsv20Balance { confirmed: bigint; pending: bigint; } enum Bsv20Status { Invalid = -1, Pending = 0, Valid = 1, } ``` ### Inscription & Content Types ```typescript type InscribeRequest = { address: string; // Where to inscribe base64Data: string; // Content (base64) mimeType: MimeTypes; // Content type map?: MAP; // Metadata satoshis?: number; // Value (default: 1) }; type RawInscription = { base64Data: string; mimeType: MimeTypes; map?: MAP; }; type MAP = { app: string; type: string; [prop: string]: string }; type MimeTypes = | "text/plain" | "text/html" | "text/css" | "application/javascript" | "application/json" | "application/xml" | "image/jpeg" | "image/png" | "image/gif" | "image/svg+xml" | "audio/mpeg" | "audio/wav" | "audio/wave" | "video/mp4" | "application/pdf" | "application/msword" | "application/vnd.ms-excel" | "application/vnd.ms-powerpoint" | "application/zip" | "application/x-7z-compressed" | "application/x-gzip" | "application/x-tar" | "application/x-bzip2"; type File = { type: string; size: number; hash: string; text?: string; json?: { [key: string]: any }; }; type Inscription = { file: File; fields?: { [key: string]: any }; parent?: string; }; ``` ### Cryptography & Signing Types ```typescript type SignMessage = { message: string; encoding?: "utf8" | "hex" | "base64"; tag?: DerivationTag; }; type SignatureRequest = { prevTxid: string; outputIndex: number; inputIndex: number; // Input index to sign satoshis: number; // Previous output value address: string | string[]; // Required signing address(es) script?: string; // Previous output script (hex) sigHashType?: number; // Default: SIGHASH_ALL | SIGHASH_FORKID csIdx?: number; // OP_CODESEPARATOR index data?: unknown; // Extra signing data }; type SignatureResponse = { inputIndex: number; sig: string; // Signature pubKey: string; // Public key sigHashType: number; csIdx?: number; }; type GetSignatures = { rawtx: string; sigRequests: SignatureRequest[]; format?: TransactionFormat; }; type EncryptRequest = { message: string; pubKeys: string[]; encoding?: "utf8" | "hex" | "base64"; tag?: DerivationTag; }; type DecryptRequest = { messages: string[]; // base64 encrypted strings tag?: DerivationTag; }; ``` ### Tagged Derivation & Utility Types ```typescript type DerivationTag = { label: string; // Human-readable tag id: string; // Unique identifier domain: string; // Requesting domain meta?: { [key: string]: any }; // Additional metadata }; type TaggedDerivationRequest = { label: string; id: string; meta?: { [key: string]: any }; }; type TaggedDerivationResponse = { address: string; pubKey: string; tag: DerivationTag; }; type GetTaggedKeysRequest = { label: string; ids?: string[]; // Filter by specific IDs }; type LockRequest = { address: string; // Where to lock (recommend identity) blockHeight: number; // Unlock block height sats: number; // Satoshis to lock }; type Broadcast = { rawtx: string; format?: TransactionFormat; // "tx" | "beef" | "ef" fund?: boolean; }; type TransactionFormat = "tx" | "beef" | "ef"; enum NetWork { Mainnet = "mainnet", Testnet = "testnet", } ``` ### Event Types ```typescript type YoursEvents = "signedOut" | "switchAccount"; type YoursEventListeners = (args?: { [key: string]: any }) => void; ``` ### Main Provider Interface ```typescript type YoursProviderType = { isReady: boolean; on: (event: YoursEvents, listener: YoursEventListeners) => void; removeListener: (event: YoursEvents, listener: YoursEventListeners) => void; connect: () => Promise; disconnect: () => Promise; isConnected: () => Promise; getPubKeys: () => Promise; getAddresses: () => Promise; getNetwork: () => Promise; getSocialProfile: () => Promise; getBalance: () => Promise; getMNEEBalance: () => Promise; getOrdinals: (params?: GetPaginatedOrdinals) => Promise; getBsv20s: () => Promise; sendBsv: (params: SendBsv[]) => Promise; sendBsv20: (params: SendBsv20) => Promise; sendMNEE: (params: SendMNEE[]) => Promise; transferOrdinal: (params: TransferOrdinal) => Promise; purchaseOrdinal: (params: PurchaseOrdinal) => Promise; purchaseBsv20: (params: PurchaseOrdinal) => Promise; signMessage: (params: SignMessage) => Promise; getSignatures: (params: GetSignatures) => Promise; broadcast: (params: Broadcast) => Promise; getExchangeRate: () => Promise; getPaymentUtxos: () => Promise; generateTaggedKeys: (params: TaggedDerivationRequest) => Promise; getTaggedKeys: (params: GetTaggedKeysRequest) => Promise; inscribe: (params: InscribeRequest[]) => Promise; lock: (params: LockRequest[]) => Promise; encrypt: (params: EncryptRequest) => Promise; decrypt: (params: DecryptRequest) => Promise; }; ``` ## Error Handling Patterns ### Standard Error Handling ```javascript try { const result = await wallet.someMethod(params); return result; } catch (error) { if (error.message?.includes('User denied')) { // User rejected the request console.log('User cancelled transaction'); } else if (error.message?.includes('Insufficient')) { // Not enough balance console.log('Insufficient funds'); } else { // Other errors console.error('Wallet error:', error); } throw error; } ``` ### Connection State Checking ```javascript const ensureConnected = async () => { if (!wallet?.isReady) { throw new Error('Wallet not installed'); } if (!await wallet.isConnected()) { await wallet.connect(); } }; ``` ## Security Considerations - **Auto-disconnect**: Wallet disconnects after 10 minutes of inactivity - **Domain whitelisting**: Successful connections whitelist your domain - **User approval**: All transactions require user confirmation - **Key isolation**: Tagged derivation keys are domain-specific - **Encryption**: Uses identity keys for encrypt/decrypt operations ## Troubleshooting ### Common Issues **Wallet not detected** ```javascript // Check installation if (typeof window === 'undefined' || !window.yours) { // Redirect to installation window.open("https://yours.org", "_blank"); } ``` **Connection failures** ```javascript // Ensure proper event handling useEffect(() => { if (!wallet?.on) return; const handleSignOut = () => { wallet.disconnect(); // Update your app state }; wallet.on('signedOut', handleSignOut); return () => wallet.removeListener('signedOut', handleSignOut); }, [wallet]); ``` **TypeScript errors** ```typescript // Add to global.d.ts declare global { interface Window { yours: YoursProviderType; } } ``` **Transaction failures** - Check balance before sending - Validate addresses/paymails - Ensure proper data encoding (hex for data arrays) - Verify UTXO availability for ordinal transfers ### Best Practices 1. **Always implement event listeners** for `switchAccount` and `signedOut` 2. **Check wallet readiness** before attempting connections 3. **Handle user rejections gracefully** 4. **Use pagination** for ordinals in wallets with many NFTs 5. **Cache exchange rates** (they're cached for 5 minutes server-side) 6. **Validate inputs** before sending to wallet methods 7. **Use identity address** for locking BSV ## Integration Examples ### Minimal Integration ```javascript // Vanilla JS if (window.yours) { const pubKey = await window.yours.connect(); const { bsvAddress } = await window.yours.getAddresses(); console.log('Connected:', bsvAddress); } ``` ### React Hook Pattern ```javascript const useWalletConnection = () => { const wallet = useYoursWallet(); const [isConnected, setIsConnected] = useState(false); useEffect(() => { if (!wallet) return; const checkConnection = async () => { setIsConnected(await wallet.isConnected()); }; checkConnection(); wallet.on('signedOut', () => setIsConnected(false)); wallet.on('switchAccount', checkConnection); return () => { wallet.removeListener('signedOut', () => setIsConnected(false)); wallet.removeListener('switchAccount', checkConnection); }; }, [wallet]); return { wallet, isConnected }; }; ``` ### Marketplace Integration ```javascript // Buy ordinal from marketplace const purchaseOrdinal = async (outpoint, marketplaceAddress) => { try { const txid = await wallet.purchaseOrdinal({ outpoint, marketplaceRate: 0.05, // 5% marketplace fee marketplaceAddress }); console.log('Purchase successful:', txid); } catch (error) { console.error('Purchase failed:', error); } }; ```