Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inline-docs, package name & v0.1.1 #2

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mesh-u5c-provider",
"version": "0.1.0",
"name": "@utxorpc/mesh-provider",
"version": "0.1.1",
"description": "An UTxO RPC provider for the Mesh transaction builder",
"main": "dist/index.js",
"scripts": {
Expand All @@ -14,9 +14,9 @@
"typescript": "^5.6.2"
},
"dependencies": {
"@meshsdk/common": "^1.7.6",
"@meshsdk/core-csl": "^1.7.6",
"@utxorpc/sdk": "^0.6.1",
"@meshsdk/common": "^1.7.9",
"@meshsdk/core-cst": "^1.7.9",
"@utxorpc/sdk": "^0.6.3",
"@utxorpc/spec": "^0.10.1"
}
}
}
185 changes: 182 additions & 3 deletions src/u5c.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,107 @@ import {
} from "@meshsdk/common";
import { Address, CardanoSDKUtil } from "@meshsdk/core-cst";

/**
* A UTxO RPC Provider for [MeshJS](https://meshjs.dev/) Transaction Builder Library.
*
* Example usage of how to use the UTxO RPC provider with Mesh to build and submit a transaction.
* ```
* // Step #1
* // Import Mesh SDK and UTxO RPC provider
* import { Transaction, MeshWallet } from "@meshsdk/core";
* import { U5CProvider } from "./u5c";
*
* async function main() {
* // Step #2
* // Create a new U5C provider
* const provider = new U5CProvider({
* url: "http://localhost:50051",
* headers: {
* "dmtr-api-key": "<api-key>",
* },
* });
*
* // Step #3
* // Create a new wallet from a mnemonic
* const wallet = new MeshWallet({
* networkId: 0, // 0: testnet, 1: mainnet
* fetcher: provider,
* submitter: provider,
* key: {
* type: "mnemonic",
* words: [
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* "solution",
* ],
* },
* });
*
* // Optional: Print the wallet address
* console.log(wallet.getChangeAddress());
*
* // Optional: Print the wallet utxos
* console.log(await provider.fetchAddressUTxOs(wallet.getChangeAddress()));
*
* // Step #4
* // Create an example transaction that sends 5 ADA to an address
* const tx = new Transaction({
* initiator: wallet,
* verbose: false,
* }).sendLovelace(
* "addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr",
* "5000000"
* );
* const unsignedTx = await tx.build();
*
* // Step #5
* // Sign the transaction
* const signedTx = wallet.signTx(unsignedTx);
*
* // Step #6
* // Submit the transaction to the blockchain network
* const txId = await provider.submitTx(signedTx);
*
* // Optional: Print the transaction ID
* console.log("Transaction ID", txId);
* }
*
* main().catch(console.error);
* ```
*/
export class U5CProvider
implements IFetcher, ISubmitter, IEvaluator, IListener
{
// Clients for querying and submitting transactions on the Cardano blockchain.
private queryClient: CardanoQueryClient;
private submitClient: CardanoSubmitClient;

/**
* Constructor initializes the query and submit clients with provided URL and optional headers.
* @param url - The base URL for interacting with Cardano nodes.
* @param headers - Optional HTTP headers for API requests.
*/
constructor({
url,
headers,
Expand All @@ -46,6 +141,12 @@ export class U5CProvider
});
}

/**
* Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called.
* @param txHash - The transaction hash to listen for confirmation
* @param callback - The callback function to call when the transaction is confirmed
* @param limit - The number of blocks to wait for confirmation
*/
onTxConfirmed(txHash: string, callback: () => void, limit = 100): void {
const onConfirmed = async () => {
const updates = this.submitClient.waitForTx(hexToBytes(txHash));
Expand All @@ -64,24 +165,43 @@ export class U5CProvider
console.log("Transaction confirmation timed out.");
}, limit * 5000);

// Start listening for confirmations
onConfirmed().finally(() => clearTimeout(timeoutId)); // Clear timeout on completion
// Start listening for confirmations and clear timeout on completion.
onConfirmed().finally(() => clearTimeout(timeoutId));
}

/**
* Evaluates the resources required to execute the transaction
* @param tx - The transaction to evaluate
*/
evaluateTx(tx: string): Promise<Omit<Action, "data">[]> {
throw new Error("Method not implemented.");
}

/**
* Submit a serialized transaction to the network.
* @param tx - The serialized transaction in hex to submit
* @returns The transaction hash of the submitted transaction
*/
async submitTx(tx: string): Promise<string> {
const cbor = toBytes(tx);
const hash = await this.submitClient.submitTx(cbor);
return bytesToHex(hash);
}

/**
* Obtain information about a specific stake account.
* @param address - Wallet address to fetch account information
*/
fetchAccountInfo(address: string): Promise<AccountInfo> {
throw new Error("Method not implemented.");
}

/**
* Fetches the UTxOs for a given address.
* @param address - The address to fetch UTxOs for
* @param asset - The asset to filter UTxOs by (optional)
* @returns UTxOs for the given address
*/
async fetchAddressUTxOs(address: string, asset?: string): Promise<UTxO[]> {
const addressBytes = Buffer.from(Address.fromBech32(address).toBytes());

Expand Down Expand Up @@ -110,30 +230,63 @@ export class U5CProvider
.filter((utxo) => utxo !== undefined); // Filter out undefined results
}

/**
* Fetches the asset addresses for a given asset.
* @param asset - The asset to fetch addresses for
*/
fetchAssetAddresses(
asset: string
): Promise<{ address: string; quantity: string }[]> {
throw new Error("Method not implemented.");
}

/**
* Fetches the metadata for a given asset.
* @param asset - The asset to fetch metadata for
*/
fetchAssetMetadata(asset: string): Promise<AssetMetadata> {
throw new Error("Method not implemented.");
}

/**
* Fetches the block information for a given block hash.
* @param hash - The block hash to fetch block information for
*/
fetchBlockInfo(hash: string): Promise<BlockInfo> {
throw new Error("Method not implemented.");
}

/**
* Fetches the collection assets for a given policy ID.
* @param policyId - The policy ID to fetch collection assets for
* @param cursor - The cursor to fetch the next set of assets (optional)
*/
fetchCollectionAssets(
policyId: string,
cursor?: number | string
): Promise<{ assets: Asset[]; next?: string | number | null }> {
throw new Error("Method not implemented.");
}

/**
* Fetches the information (AssetMetadata) for a given handle.
* @param handle - The handle to fetch information for
*/
fetchHandle(handle: string): Promise<object> {
throw new Error("Method not implemented.");
}

/**
* Resolve the handle's address from the handle.
* @param handle - The handle to resolve
*/
fetchHandleAddress(handle: string): Promise<string> {
throw new Error("Method not implemented.");
}

/**
* Fetches protocol parameters
*/
async fetchProtocolParameters(epoch: number): Promise<Protocol> {
const rpcPParams = await this.queryClient.readParams();
if (rpcPParams === undefined || rpcPParams === null) {
Expand All @@ -143,16 +296,32 @@ export class U5CProvider
return this._rpcPParamsToProtocol(rpcPParams);
}

/**
* Fetches transaction info for a given hash.
* @param hash - The transaction hash
*/
fetchTxInfo(hash: string): Promise<TransactionInfo> {
throw new Error("Method not implemented.");
}

/**
* Fetches output UTxOs of a given transaction hash.
* @param hash - The transaction hash
*/
fetchUTxOs(hash: string): Promise<UTxO[]> {
throw new Error("Method not implemented.");
}

get(url: string): Promise<any> {
throw new Error("Method not implemented.");
}

/**
* Waits for transaction confirmation within a given timeout.
* @param txId - The transaction hash.
* @param timeout - Optional timeout in milliseconds.
* @returns True if the transaction is confirmed within the timeout, otherwise false.
*/
awaitTransactionConfirmation(
txId: string,
timeout?: number
Expand All @@ -176,6 +345,12 @@ export class U5CProvider
return Promise.race([onConfirmed, onTimeout]);
}

/**
* Helper function to convert an RPC UTxO object to a Mesh UTxO object.
* @param rpcTxoRef - The transaction output reference from RPC.
* @param rpcTxOutput - The transaction output details from RPC.
* @returns A formatted UTxO object.
*/
private _rpcUtxoToMeshUtxo(
rpcTxoRef: spec.query.TxoRef,
rpcTxOutput: spec.cardano.TxOutput
Expand Down Expand Up @@ -240,12 +415,16 @@ export class U5CProvider
};
}

/**
* Converts RPC protocol parameters to a Mesh Protocol object.
* @param rpcPParams - The protocol parameters from the RPC.
* @returns A Protocol object.
*/
private _rpcPParamsToProtocol(rpcPParams: spec.cardano.PParams): Protocol {
return castProtocol({
coinsPerUtxoSize: Number(rpcPParams.coinsPerUtxoByte),
collateralPercent: Number(rpcPParams.collateralPercentage),
decentralisation: 0, // Deprecated in Babbage era.
// epoch: ,
keyDeposit: Number(rpcPParams.stakeKeyDeposit),
maxBlockExMem: Number(rpcPParams.maxExecutionUnitsPerBlock?.memory),
maxBlockExSteps: Number(rpcPParams.maxExecutionUnitsPerBlock?.steps),
Expand Down