From a392462f1282786d8436e3d42cecbb98d35fb164 Mon Sep 17 00:00:00 2001 From: Harvey Zuccon Date: Mon, 7 Apr 2025 06:40:02 +0000 Subject: [PATCH] Resolve "feat(Docs): Add BlockchainElectrum Tool" --- packages/docs/src/.vitepress/config.ts | 15 +---- .../theme/components/PrimitiveTool.vue | 12 ++-- .../src/tools/stack/blockchain-functions.ts | 60 +++++++++++++++++++ packages/docs/src/tools/stack/blockchain.md | 30 ++++++++++ .../src/blockchain/blockchain-electrum.ts | 40 +++++++++++-- 5 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 packages/docs/src/tools/stack/blockchain-functions.ts create mode 100644 packages/docs/src/tools/stack/blockchain.md diff --git a/packages/docs/src/.vitepress/config.ts b/packages/docs/src/.vitepress/config.ts index 4c0fb36..c2959b1 100644 --- a/packages/docs/src/.vitepress/config.ts +++ b/packages/docs/src/.vitepress/config.ts @@ -207,29 +207,16 @@ export default withMermaid({ text: 'Stack', collapsed: false, items: [ - /* { text: 'Blockchain', link: '/tools/stack/blockchain', items: [ { text: 'Electrum', - link: '/tools/stack/blockchain#encryption', + link: '/tools/stack/blockchain#electrum', }, ], }, - { - text: 'Utils', - link: '/tools/stack/utils', - items: [ - { - text: 'Encrypter', - link: '/tools/stack/utils#encrypter', - }, - { text: 'Hasher', link: '/tools/stack/utils#hasher' }, - ], - }, - */ ], }, ], diff --git a/packages/docs/src/.vitepress/theme/components/PrimitiveTool.vue b/packages/docs/src/.vitepress/theme/components/PrimitiveTool.vue index 91a77ff..15cef2a 100644 --- a/packages/docs/src/.vitepress/theme/components/PrimitiveTool.vue +++ b/packages/docs/src/.vitepress/theme/components/PrimitiveTool.vue @@ -75,7 +75,7 @@
- +
@@ -135,7 +135,7 @@ export interface Method { error?: string; // Function that takes the models and returns the primitive - callback: (primitive: Primitive, value: Array) => string; + callback: (primitive: Primitive, value: Array) => string | Promise; // Whether the input is extended onto a new line extendedInput?: boolean @@ -185,13 +185,13 @@ const state: Ref<{ primitive: undefined, }) -async function setPrimitive(functionToExecute: () => Primitive | Promise): void { +async function setPrimitive(functionToExecute: () => Primitive | Promise): Promise { try { state.value.primitive = await functionToExecute(); state.value.error = undefined; - state.value.toFunctions.forEach((wrappedMethod, i) => { - state.value.toFunctions[i].result = wrappedMethod.callback(state.value.primitive) + state.value.toFunctions.forEach(async (wrappedMethod, i) => { + state.value.toFunctions[i].result = await wrappedMethod.callback(state.value.primitive) }); state.value.methods.forEach((method, i) => { @@ -218,7 +218,7 @@ function getPrimitive(functionToExecute: () => string): string { } } -async function executeMethod(wrappedMethod: () => string | Promise): string { +async function executeMethod(wrappedMethod: () => string | Promise): Promise { try { if(!state.value.primitive) { return ''; diff --git a/packages/docs/src/tools/stack/blockchain-functions.ts b/packages/docs/src/tools/stack/blockchain-functions.ts new file mode 100644 index 0000000..c6ca05b --- /dev/null +++ b/packages/docs/src/tools/stack/blockchain-functions.ts @@ -0,0 +1,60 @@ +import { BlockchainElectrum, encodeExtendedJson, Transaction } from '@xocash/stack'; + +export const electrumClient = { + from: [ + { + label: 'From Servers', + inputs: ['Servers'], + models: ['bch.imaginary.cash, cashnode.bch.ninja, electrum.imaginary.cash'], + callback: async (args: [string]) => { + const electrum = await BlockchainElectrum.from({ + opts: { + servers: args[0].replaceAll(' ', '').split(','), + application: 'XO-tools', + }, + }); + + return electrum; + }, + }, + ], + to: [], + methods: [ + { + label: 'Fetch Unspents', + inputs: ['Address'], + models: ['Address'], + callback: async (electrum: BlockchainElectrum, args: [string]) => { + const unspents = await electrum.fetchUnspents(args[0]); + return encodeExtendedJson(unspents.toArray(), 2); + }, + }, + { + label: 'Fetch Transaction', + inputs: ['Transaction Hash'], + models: ['Transaction Hash'], + callback: async (electrum: BlockchainElectrum, args: [string]) => { + const transaction = await electrum.fetchTransaction(args[0]); + return encodeExtendedJson(transaction, 2); + }, + }, + { + label: 'Fetch Transactions', + inputs: ['Address'], + models: ['Address'], + callback: async (electrum: BlockchainElectrum, args: [string]) => { + const transactions = await electrum.fetchTransactions(args[0]); + return encodeExtendedJson(transactions.toArray(), 2); + }, + }, + { + label: 'Broadcast Transaction', + inputs: ['Transaction'], + models: ['Transaction'], + callback: async (electrum: BlockchainElectrum, args: [string]) => { + const tx = Transaction.from(args[0]); + return await electrum.broadcastTransaction(tx); + }, + }, + ], +}; \ No newline at end of file diff --git a/packages/docs/src/tools/stack/blockchain.md b/packages/docs/src/tools/stack/blockchain.md new file mode 100644 index 0000000..68f02ad --- /dev/null +++ b/packages/docs/src/tools/stack/blockchain.md @@ -0,0 +1,30 @@ +--- +aside: false +--- + + + + + +# Blockchain + +## Electrum Client + +
+

A connection to Electrum servers.

+

Mutliple servers can be provided, and the client will attempt to fallback to the next server in case of failure.

+

Servers can be provided as a comma separated list.

+ + +
\ No newline at end of file diff --git a/packages/stack/src/blockchain/blockchain-electrum.ts b/packages/stack/src/blockchain/blockchain-electrum.ts index 225d45c..16912d8 100644 --- a/packages/stack/src/blockchain/blockchain-electrum.ts +++ b/packages/stack/src/blockchain/blockchain-electrum.ts @@ -48,6 +48,11 @@ export type BlockchainElectrumOpts = { application: string; }; +export type BlockchainElectrumParams = { + store?: BaseStore; + opts?: Partial; +}; + export class BlockchainElectrum extends BaseBlockchain { // Composables. electrumClient!: ElectrumClient; @@ -60,18 +65,43 @@ export class BlockchainElectrum extends BaseBlockchain { addressSubscriptions: Map> = new Map(); transactionSubscriptions: Map> = new Map(); + // Options + store: BaseStore; + opts: BlockchainElectrumOpts; + constructor( - public readonly store: BaseStore = new StoreInMemory(), - public readonly opts: BlockchainElectrumOpts = { + public readonly params: BlockchainElectrumParams = {}, + ) { + super(); + + // Set the store, or use the memory store by default. + this.store = params.store ?? new StoreInMemory(); + + // Combine provided options with default options. + this.opts = { servers: [ 'bch.imaginary.cash', 'cashnode.bch.ninja', 'electrum.imaginary.cash', ], application: 'XOApp', - }, - ) { - super(); + ...params.opts, + }; + } + + /** + * Creates a new BlockchainElectrum instance. + * @param {BlockchainElectrumParams} params - The parameters for the BlockchainElectrum instance. + * @returns {BlockchainElectrum} A new BlockchainElectrum instance. + */ + static async from( + params: BlockchainElectrumParams = {}, + ): Promise { + const blockchain = new BlockchainElectrum(params); + + await blockchain.start(); + + return blockchain; } async start() {