@vechain/sdk-network
Version:
This module serves as the standard interface connecting decentralized applications (dApps) and users to the VeChainThor blockchain
160 lines (146 loc) • 5.62 kB
text/typescript
import { Hex, HexUInt, type Transaction } from '@vechain/sdk-core';
import { NotDelegatedTransaction } from '@vechain/sdk-errors';
import {
type GetDelegationSignatureResult,
type SignTransactionOptions
} from '../types';
import { type HttpClient, HttpMethod } from '../../../http';
/**
* Retrieves the signature of a delegation transaction from a gasPayer given the endpoint
* from which to retrieve the signature.
*
* @see [Simple Gas Payer Standard](https://github.com/vechain/VIPs/blob/master/vips/VIP-201.md)
*
* @param tx - The transaction to delegate.
* @param gasPayerServiceUrl - The URL of the endpoint of the gasPayer service.
* @param originAddress - The address of the origin account.
* @param httpClient - The HTTP client instance used for making HTTP requests.
* @returns A promise that resolves to the signature of the delegation transaction.
* @throws {NotDelegatedTransaction}
*/
const _getDelegationSignature = async (
tx: Transaction,
gasPayerServiceUrl: string,
originAddress: string,
httpClient: HttpClient
): Promise<Uint8Array> => {
const rawTx = Hex.of(tx.encoded).toString();
/**
* The request body for the delegation transaction.
*
* @see [Obtaining Gas Payer Signature](https://github.com/vechain/VIPs/blob/master/vips/VIP-201.md#obtaining-gas-payer-signature)
*/
const sponsorRequestBody = {
origin: originAddress,
raw: rawTx
};
try {
const response = (await httpClient.http(
HttpMethod.POST,
gasPayerServiceUrl,
{
body: sponsorRequestBody,
headers: { 'Content-Type': 'application/json' }
}
)) as GetDelegationSignatureResult;
return HexUInt.of(response.signature.slice(2)).bytes;
} catch (error) {
throw new NotDelegatedTransaction(
'_getDelegationSignature()',
'Delegation failed: Cannot get signature from gasPayerUrl.',
{
gasPayerUrl: gasPayerServiceUrl
},
error
);
}
};
/**
* Provide a set of utils for the delegation type.
* It is a mutual exclusion between gasPayerPrivateKey and gasPayerServiceUrl. (@see SignTransactionOptions)
*
* The aim of this handler is to:
* - Understand the kind of delegation and the delegation info
* - Provide a method to get the delegation signature
*
* @param gasPayer - The gasPayer options.
*/
const DelegationHandler = (
gasPayer?: SignTransactionOptions | null
): {
isDelegated: () => boolean;
gasPayerOrUndefined: () => SignTransactionOptions | undefined;
gasPayerOrNull: () => SignTransactionOptions | null;
getDelegationSignatureUsingUrl: (
tx: Transaction,
originAddress: string,
httpClient: HttpClient
) => Promise<Uint8Array>;
} => {
// Check if gasPayer is undefined (null or undefined)
const gasPayerIsUndefined = gasPayer === undefined || gasPayer === null;
// Check if is delegated by url
const isDelegatedWithUrl =
!gasPayerIsUndefined && gasPayer?.gasPayerServiceUrl !== undefined;
// Check if is delegated by private key
const isDelegatedWithPrivateKey =
!gasPayerIsUndefined && gasPayer?.gasPayerPrivateKey !== undefined;
return {
/**
* Check if the transaction is delegated.
*
* @returns true if the transaction is delegated, false otherwise.
*/
isDelegated: (): boolean =>
isDelegatedWithUrl || isDelegatedWithPrivateKey,
/**
* Get the gasPayer options or undefined.
* (if gasPayer is undefined or null).
*
* @returns The gasPayer options or undefined.
*/
gasPayerOrUndefined: (): SignTransactionOptions | undefined =>
gasPayerIsUndefined ? undefined : gasPayer,
/**
* Get the gasPayer options or null.
* (if gasPayer is undefined or null).
*
* @returns The gasPayer options or null.
*/
gasPayerOrNull: (): SignTransactionOptions | null =>
gasPayerIsUndefined ? null : gasPayer,
/**
* Retrieves the signature of a delegation transaction from a gasPayer given the endpoint
* from which to retrieve the signature.
*
* @see [Simple Gas Payer Standard](https://github.com/vechain/VIPs/blob/master/vips/VIP-201.md)
*
* @param tx - The transaction to delegate.
* @param originAddress - The address of the origin account.
* @param httpClient - The HTTP client instance used for making HTTP requests.
* @returns A promise that resolves to the signature of the delegation transaction.
* @throws {NotDelegatedTransaction}
*/
getDelegationSignatureUsingUrl: async (
tx: Transaction,
originAddress: string,
httpClient: HttpClient
): Promise<Uint8Array> => {
// Cannot be delegated by private key
if (!isDelegatedWithUrl) {
throw new NotDelegatedTransaction(
'DelegationHandler.getDelegationSignatureUsingUrl()',
'Delegation with url failed: gasPayerServiceUrl is not defined.',
undefined
);
}
return await _getDelegationSignature(
tx,
gasPayer?.gasPayerServiceUrl,
originAddress,
httpClient
);
}
};
};
export { DelegationHandler };