Skip to content

Commit

Permalink
Merge pull request #20 from secretkeylabs/edu/misc-changes
Browse files Browse the repository at this point in the history
Support for getBalance
  • Loading branch information
aryzing authored Jul 1, 2024
2 parents be8ef48 + daca9f6 commit f9fbf35
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 113 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"test": "jest",
"build-debug": "webpack --mode development",
"build": "npm run clean && tsup src/index.ts --format esm --dts",
"build:watch": "npm run clean && tsup src/index.ts --format esm --dts --watch",
"clean": "rimraf dist",
"lint": "prettier --write .",
"prepare": "husky install"
Expand Down
3 changes: 2 additions & 1 deletion src/provider/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
BtcRequestMethod,
OrdinalsRequestMethod,
Params,
Requests,
RunesRequestMethod,
Expand Down Expand Up @@ -46,7 +47,7 @@ export interface Provider {
mozillaAddOnsUrl?: string;
googlePlayStoreUrl?: string;
iOSAppStoreUrl?: string;
methods?: (StxRequestMethod | BtcRequestMethod | RunesRequestMethod)[];
methods?: (StxRequestMethod | BtcRequestMethod | RunesRequestMethod | OrdinalsRequestMethod)[];
}

export interface SupportedWallet extends Provider {
Expand Down
33 changes: 22 additions & 11 deletions src/request/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { getProviderById } from '../provider';
import { RpcBase, RpcResult, RpcSuccessResponse } from '../types';
import { Params, Requests } from './types';
import {
RpcErrorCode,
RpcResult,
rpcErrorResponseMessageSchema,
rpcSuccessResponseMessageSchema,
} from '../types';
import * as v from 'valibot';
import { Params, Requests, Return } from './types';

export const request = async <Method extends keyof Requests>(
method: Method,
Expand All @@ -20,23 +26,28 @@ export const request = async <Method extends keyof Requests>(

const response = await provider.request(method, params);

if (isRpcSuccessResponse<Method>(response)) {
if (v.is(rpcErrorResponseMessageSchema, response)) {
return {
status: 'error',
error: response.error,
};
}

if (v.is(rpcSuccessResponseMessageSchema, response)) {
return {
status: 'success',
result: response.result,
result: response.result as Return<Method>,
};
}

return {
status: 'error',
error: response.error,
error: {
code: RpcErrorCode.INTERNAL_ERROR,
message: 'Received unknown response from provider.',
data: response,
},
};
};

const isRpcSuccessResponse = <Method extends keyof Requests>(
response: RpcBase
): response is RpcSuccessResponse<Method> => {
return Object.hasOwn(response, 'result') && !!(response as RpcSuccessResponse<Method>).result;
};

export * from './types';
53 changes: 51 additions & 2 deletions src/request/types/btcMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { MethodParamsAndResult, rpcRequestMessageSchema } from '../../types';
import * as v from 'valibot';

export const getInfoMethodName = 'getInfo';
export const getInfoParamsSchema = v.null();
export const getInfoParamsSchema = v.nullish(v.null());
export type GetInfoParams = v.InferOutput<typeof getInfoParamsSchema>;
export const getInfoResultSchema = v.object({
/**
* Version of the wallet.
Expand All @@ -24,14 +25,16 @@ export const getInfoResultSchema = v.object({
*/
supports: v.array(v.string()),
});
export const getInfoSchema = v.object({
export type GetInfoResult = v.InferOutput<typeof getInfoResultSchema>;
export const getInfoRequestMessageSchema = v.object({
...rpcRequestMessageSchema.entries,
...v.object({
method: v.literal(getInfoMethodName),
params: getInfoParamsSchema,
id: v.string(),
}).entries,
});
export type GetInfoRequestMessage = v.InferOutput<typeof getInfoRequestMessageSchema>;
export type GetInfo = MethodParamsAndResult<
v.InferOutput<typeof getInfoParamsSchema>,
v.InferOutput<typeof getInfoResultSchema>
Expand All @@ -49,12 +52,14 @@ export const getAddressesParamsSchema = v.object({
*/
message: v.optional(v.string()),
});
export type GetAddressesParams = v.InferOutput<typeof getAddressesParamsSchema>;
export const getAddressesResultSchema = v.object({
/**
* The addresses generated for the given purposes.
*/
addresses: v.array(addressSchema),
});
export type GetAddressesResult = v.InferOutput<typeof getAddressesResultSchema>;
export const getAddressesRequestMessageSchema = v.object({
...rpcRequestMessageSchema.entries,
...v.object({
Expand All @@ -63,6 +68,7 @@ export const getAddressesRequestMessageSchema = v.object({
id: v.string(),
}).entries,
});
export type GetAddressesRequestMessage = v.InferOutput<typeof getAddressesRequestMessageSchema>;
export type GetAddresses = MethodParamsAndResult<
v.InferOutput<typeof getAddressesParamsSchema>,
v.InferOutput<typeof getAddressesResultSchema>
Expand All @@ -79,6 +85,7 @@ export const signMessageParamsSchema = v.object({
**/
message: v.string(),
});
export type SignMessageParams = v.InferOutput<typeof signMessageParamsSchema>;
export const signMessageResultSchema = v.object({
/**
* The signature of the message.
Expand All @@ -93,6 +100,7 @@ export const signMessageResultSchema = v.object({
*/
address: v.string(),
});
export type SignMessageResult = v.InferOutput<typeof signMessageResultSchema>;
export const signMessageRequestMessageSchema = v.object({
...rpcRequestMessageSchema.entries,
...v.object({
Expand All @@ -101,6 +109,7 @@ export const signMessageRequestMessageSchema = v.object({
id: v.string(),
}).entries,
});
export type SignMessageRequestMessage = v.InferOutput<typeof signMessageRequestMessageSchema>;
export type SignMessage = MethodParamsAndResult<
v.InferOutput<typeof signMessageParamsSchema>,
v.InferOutput<typeof signMessageResultSchema>
Expand Down Expand Up @@ -170,7 +179,9 @@ export type SignPsbt = MethodParamsAndResult<SignPsbtParams, SignPsbtResult>;

export const getAccountsMethodName = 'getAccounts';
export const getAccountsParamsSchema = getAddressesParamsSchema;
export type GetAccountsParams = v.InferOutput<typeof getAccountsParamsSchema>;
export const getAccountsResultSchema = v.array(addressSchema);
export type GetAccountsResult = v.InferOutput<typeof getAccountsResultSchema>;
export const getAccountsRequestMessageSchema = v.object({
...rpcRequestMessageSchema.entries,
...v.object({
Expand All @@ -179,7 +190,45 @@ export const getAccountsRequestMessageSchema = v.object({
id: v.string(),
}).entries,
});
export type GetAccountsRequestMessage = v.InferOutput<typeof getAccountsRequestMessageSchema>;
export type GetAccounts = MethodParamsAndResult<
v.InferOutput<typeof getAccountsParamsSchema>,
v.InferOutput<typeof getAccountsResultSchema>
>;

// Get the balance of the current Bitcoin account.
export const getBalanceMethodName = 'getBalance';
export const getBalanceParamsSchema = v.nullish(v.null());
export const getBalanceResultSchema = v.object({
/**
* The confirmed balance of the wallet in sats. Using a string due to chrome
* messages not supporting bigint
* (https://issues.chromium.org/issues/40116184).
*/
confirmed: v.string(),

/**
* The unconfirmed balance of the wallet in sats. Using a string due to chrome
* messages not supporting bigint
* (https://issues.chromium.org/issues/40116184).
*/
unconfirmed: v.string(),

/**
* The total balance (both confirmed and unconfrimed UTXOs) of the wallet in
* sats. Using a string due to chrome messages not supporting bigint
* (https://issues.chromium.org/issues/40116184).
*/
total: v.string(),
});
export const getBalanceRequestMessageSchema = v.object({
...rpcRequestMessageSchema.entries,
...v.object({
method: v.literal(getBalanceMethodName),
id: v.string(),
}).entries,
});
export type GetBalance = MethodParamsAndResult<
v.InferOutput<typeof getBalanceParamsSchema>,
v.InferOutput<typeof getBalanceResultSchema>
>;
93 changes: 39 additions & 54 deletions src/request/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,80 +1,65 @@
import {
GetAccounts,
GetAddresses,
GetInfo,
SendTransfer,
SignMessage,
SignPsbt,
} from './btcMethods';
import {
EstimateRbfOrder,
EstimateRunesEtch,
EstimateRunesMint,
EtchRunes,
GetOrder,
GetRunesBalance,
MintRunes,
RbfOrder,
} from './runesMethods';
import {
StxCallContract,
StxDeployContract,
StxGetAccounts,
StxGetAddresses,
StxSignStructuredMessage,
StxSignStxMessage,
StxSignTransaction,
StxTransferStx,
} from './stxMethods';
import { Connect, Disconnect } from './walletMethods';
import type * as BtcMethods from './btcMethods';
import { GetInscriptions } from './ordinalsMethods';
import type * as RunesMethods from './runesMethods';
import type * as StxMethods from './stxMethods';
import { RequestPermissions, RenouncePermissions } from './walletMethods';

export interface StxRequests {
stx_callContract: StxCallContract;
stx_deployContract: StxDeployContract;
stx_getAccounts: StxGetAccounts;
stx_getAddresses: StxGetAddresses;
stx_signMessage: StxSignStxMessage;
stx_signStructuredMessage: StxSignStructuredMessage;
stx_signTransaction: StxSignTransaction;
stx_transferStx: StxTransferStx;
stx_callContract: StxMethods.StxCallContract;
stx_deployContract: StxMethods.StxDeployContract;
stx_getAccounts: StxMethods.StxGetAccounts;
stx_getAddresses: StxMethods.StxGetAddresses;
stx_signMessage: StxMethods.StxSignStxMessage;
stx_signStructuredMessage: StxMethods.StxSignStructuredMessage;
stx_signTransaction: StxMethods.StxSignTransaction;
stx_transferStx: StxMethods.StxTransferStx;
}

export type StxRequestMethod = keyof StxRequests;

export interface BtcRequests {
getInfo: GetInfo;
getAddresses: GetAddresses;
getAccounts: GetAccounts;
signMessage: SignMessage;
sendTransfer: SendTransfer;
signPsbt: SignPsbt;
getInfo: BtcMethods.GetInfo;
getAddresses: BtcMethods.GetAddresses;
getAccounts: BtcMethods.GetAccounts;
getBalance: BtcMethods.GetBalance;
signMessage: BtcMethods.SignMessage;
sendTransfer: BtcMethods.SendTransfer;
signPsbt: BtcMethods.SignPsbt;
}

export type BtcRequestMethod = keyof BtcRequests;

export interface RunesRequests {
runes_estimateMint: EstimateRunesMint;
runes_mint: MintRunes;
runes_estimateEtch: EstimateRunesEtch;
runes_etch: EtchRunes;
runes_getOrder: GetOrder;
runes_estimateRbfOrder: EstimateRbfOrder;
runes_rbfOrder: RbfOrder;
runes_getBalance: GetRunesBalance;
runes_estimateMint: RunesMethods.EstimateRunesMint;
runes_mint: RunesMethods.MintRunes;
runes_estimateEtch: RunesMethods.EstimateRunesEtch;
runes_etch: RunesMethods.EtchRunes;
runes_getOrder: RunesMethods.GetOrder;
runes_estimateRbfOrder: RunesMethods.EstimateRbfOrder;
runes_rbfOrder: RunesMethods.RbfOrder;
runes_getBalance: RunesMethods.GetRunesBalance;
}

export type RunesRequestMethod = keyof RunesRequests;

export interface OrdinalsRequests {
ord_getInscriptions: GetInscriptions;
}

export type OrdinalsRequestMethod = keyof OrdinalsRequests;

export interface WalletMethods {
wallet_connect: Connect;
wallet_disconnect: Disconnect;
wallet_requestPermissions: RequestPermissions;
wallet_renouncePermissions: RenouncePermissions;
}

export type Requests = BtcRequests & StxRequests & RunesRequests & WalletMethods;
export type Requests = BtcRequests & StxRequests & RunesRequests & WalletMethods & OrdinalsRequests;

export type Return<Method> = Method extends keyof Requests ? Requests[Method]['result'] : never;
export type Params<Method> = Method extends keyof Requests ? Requests[Method]['params'] : never;

export * from './stxMethods';
export * from './btcMethods';
export * from './walletMethods';
export * from './runesMethods';
export * from './ordinalsMethods';
38 changes: 38 additions & 0 deletions src/request/types/ordinalsMethods.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { MethodParamsAndResult, rpcRequestMessageSchema } from '../../types';
import * as v from 'valibot';

export const getInscriptionsMethodName = 'ord_getInscriptions';
export const getInscriptionsParamsSchema = v.object({
offset: v.number(),
limit: v.number(),
});
export const getInscriptionsResultSchema = v.object({
inscriptions: v.array(
v.object({
inscriptionId: v.string(),
inscriptionNumber: v.string(),
address: v.string(),
collectionName: v.optional(v.string()),
postage: v.string(),
contentLength: v.string(),
contentType: v.string(),
timestamp: v.number(),
offset: v.number(),
genesisTransaction: v.string(),
output: v.string(),
})
),
});
export const getInscriptionsSchema = v.object({
...rpcRequestMessageSchema.entries,
...v.object({
method: v.literal(getInscriptionsMethodName),
params: getInscriptionsParamsSchema,
id: v.string(),
}).entries,
});

export type GetInscriptions = MethodParamsAndResult<
v.InferOutput<typeof getInscriptionsParamsSchema>,
v.InferOutput<typeof getInscriptionsResultSchema>
>;
Loading

0 comments on commit f9fbf35

Please sign in to comment.