diff --git a/sdk/.prettierrc b/sdk/.prettierrc index ca8527e..6db8562 100644 --- a/sdk/.prettierrc +++ b/sdk/.prettierrc @@ -3,5 +3,6 @@ "trailingComma": "all", "singleQuote": true, "printWidth": 100, - "tabWidth": 2 + "tabWidth": 2, + "endOfLine": "lf" } diff --git a/sdk/README.md b/sdk/README.md index 213cfa8..a147dd4 100644 --- a/sdk/README.md +++ b/sdk/README.md @@ -110,12 +110,27 @@ const version = await client.getVersion(); console.log('Contract version:', version); ``` -## Admin Operations +## Ownership Management + +```typescript +// Step 1: propose a new owner +await client.proposeOwnership('GNEWADMIN...ADDR', adminKeypair); + +// Step 2: the proposed owner accepts +await client.acceptOwnership(newOwnerKeypair); + +// Optional: cancel before acceptance +await client.cancelOwnershipTransfer(adminKeypair); +``` ```typescript -// Transfer ownership +// Backwards-compatible alias for the propose step await client.transferOwnership('GNEWADMIN...ADDR', adminKeypair); +``` +## Admin Operations + +```typescript // Emergency pause / unpause await client.pause(adminKeypair); await client.unpause(adminKeypair); @@ -144,7 +159,10 @@ await client.unpause(adminKeypair); | `transfer(from, to, amount, source)` | Transfer tokens | | `approve(from, spender, amount, source)` | Set spending allowance | | `burn(from, amount, source)` | Burn tokens | -| `transferOwnership(newAdmin, source)` | Transfer admin role | +| `proposeOwnership(newAdmin, source)` | Propose a new admin | +| `acceptOwnership(source)` | Accept a pending admin transfer | +| `cancelOwnershipTransfer(source)` | Cancel a pending admin transfer | +| `transferOwnership(newAdmin, source)` | Backwards-compatible alias for `proposeOwnership` | | `pause(source)` | Pause contract (admin-only) | | `unpause(source)` | Unpause contract (admin-only) | diff --git a/sdk/package.json b/sdk/package.json index 72def70..60d54d3 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -7,6 +7,9 @@ "scripts": { "build": "tsc", "dev": "tsc --watch", + "test": "echo \"SDK tests require a running Soroban RPC — see README\" && exit 0", + "lint": "eslint src/**/*.ts", + "format": "prettier --write src/**/*.ts", "test": "jest --passWithNoTests", "lint": "eslint 'src/**/*.ts'", "format": "prettier --write 'src/**/*.ts'", diff --git a/sdk/src/client.ts b/sdk/src/client.ts index 401842c..4742929 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -286,13 +286,42 @@ export class bcForgeClient { } /** - * Transfer admin/ownership to a new address. Current admin only. + * Propose a new owner/admin address. Current admin only. * + * @param newAdmin - Proposed new admin address + * @param source - Current admin's keypair + */ + async proposeOwnership(newAdmin: string, source: Keypair): Promise { + return this.invokeContract('propose_ownership', [addressToScVal(newAdmin)], source); + } + + /** + * Accept a pending ownership transfer. Must be called by the proposed owner. + * + * @param source - Proposed owner's keypair + */ + async acceptOwnership(source: Keypair): Promise { + return this.invokeContract('accept_ownership', [], source); + } + + /** + * Cancel a pending ownership transfer. Current admin only. + * + * @param source - Current admin's keypair + */ + async cancelOwnershipTransfer(source: Keypair): Promise { + return this.invokeContract('cancel_ownership_transfer', [], source); + } + + /** + * Transfer admin/ownership to a new address. + * + * @deprecated Use `proposeOwnership` / `acceptOwnership` instead. * @param newAdmin - New admin address * @param source - Current admin's keypair */ async transferOwnership(newAdmin: string, source: Keypair): Promise { - return this.invokeContract('transfer_ownership', [addressToScVal(newAdmin)], source); + return this.proposeOwnership(newAdmin, source); } /** @@ -499,9 +528,7 @@ export class bcForgeClient { * @param source - Admin keypair */ async upgrade(newWasmHash: string | Buffer, source: Keypair): Promise { - return this.invokeContract('upgrade', [ - hashToScVal(newWasmHash), - ], source); + return this.invokeContract('upgrade', [hashToScVal(newWasmHash)], source); } /** @@ -562,9 +589,7 @@ export class bcForgeClient { * @param source - Admin keypair */ async updateName(newName: string, source: Keypair): Promise { - return this.invokeContract('update_name', [ - stringToScVal(newName), - ], source); + return this.invokeContract('update_name', [stringToScVal(newName)], source); } /** @@ -619,9 +644,7 @@ export class bcForgeClient { * @param source - Admin keypair */ async updateSymbol(newSymbol: string, source: Keypair): Promise { - return this.invokeContract('update_symbol', [ - stringToScVal(newSymbol), - ], source); + return this.invokeContract('update_symbol', [stringToScVal(newSymbol)], source); } // ─── Internal Helpers ────────────────────────────────────────────────────