@joyid/common
Version:
Shared code for JoyID SDK
631 lines (612 loc) • 22.7 kB
text/typescript
import { RequireExactlyOne } from 'type-fest';
import { TypedData, TypedDataToPrimitiveTypes, TypedDataDomain } from 'abitype';
declare enum DappErrorName {
DecodeError = "Decode Error",
InvalidParams = "Invalid Params",
UserRejected = "User Rejected",
NotAllowed = "Not Allowed"
}
declare class DappError extends Error {
rawError?: unknown;
constructor(message: string, name?: string, rawError?: unknown);
}
declare function parseSearchWith(parser: (str: string) => any): (searchStr: string) => any;
declare function stringifySearchWith(stringify: (search: any) => string, parser?: (str: string) => any): (search: Record<string, any>) => string;
declare const decodeSearch: (searchStr: string) => any;
declare const encodeSearch: (search: Record<string, any>) => string;
declare const safeExec: <T>(fn: () => T) => T | null;
/**
* Convert from a Base64URL-encoded string to an Array Buffer. Best used when converting a
* credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
* excludeCredentials
*
* Helper method to compliment `bufferToBase64URLString`
*/
declare function base64URLStringToBuffer(base64URLString: string): ArrayBuffer;
/**
* Convert the given array buffer into a Base64URL-encoded string. Ideal for converting various
* credential response ArrayBuffers to string for sending back to the server as JSON.
*
* Helper method to compliment `base64URLStringToBuffer`
*/
declare function bufferToBase64URLString(buffer: ArrayBuffer): string;
declare function hexToArrayBuffer(input: string): ArrayBuffer;
declare function bufferToHex(buffer: ArrayBuffer): string;
declare function appendBuffer(buffer1: ArrayBuffer, buffer2: ArrayBuffer): ArrayBuffer;
declare function bufferToUTF8String(value: ArrayBuffer): string;
declare function utf8StringToBuffer(value: string): ArrayBuffer;
declare function hexToUTF8String(value: string): string;
declare function remove0x(hex: string): string;
declare function append0x(hex: string): string;
declare function hexToString(hex: string): string;
declare function base64urlToHex(s: string): string;
declare function isStandaloneBrowser(): boolean;
type Hash = string;
type HexNumber = string;
type HexString = string;
type PackedSince = string;
interface Header {
timestamp: HexNumber;
number: HexNumber;
epoch: HexNumber;
compactTarget: HexNumber;
dao: Hash;
hash: Hash;
nonce: HexNumber;
parentHash: Hash;
proposalsHash: Hash;
transactionsRoot: Hash;
extraHash: Hash;
version: HexNumber;
}
declare type HashType = 'type' | 'data' | 'data1';
interface Script {
codeHash: Hash;
hashType: HashType;
args: HexString;
}
interface OutPoint {
txHash: Hash;
index: HexNumber;
}
declare type DepType = 'depGroup' | 'code';
interface CellDep {
outPoint: OutPoint;
depType: DepType;
}
interface Input {
previousOutput: OutPoint;
since: PackedSince;
}
interface Output {
capacity: HexString;
lock: Script;
type?: Script;
}
interface WitnessArgs {
lock?: HexString;
inputType?: HexString;
outputType?: HexString;
}
interface RawTransaction {
cellDeps: CellDep[];
hash?: Hash;
headerDeps: Hash[];
inputs: Input[];
outputs: Output[];
outputsData: HexString[];
version: HexString;
}
interface CKBTransaction {
cellDeps: CellDep[];
hash?: Hash;
headerDeps: Hash[];
inputs: Input[];
outputs: Output[];
outputsData: HexString[];
version: HexNumber;
witnesses: HexString[];
}
interface CkbTransactionRequest {
from: string;
to: string;
amount: string;
}
interface CkbDappConfig extends JoyIDConfig {
name?: string;
logo?: string;
redirectURL?: string;
rpcURL?: string;
network?: 'mainnet' | 'testnet';
}
interface SignCkbTxRequest extends CkbDappConfig {
tx: CkbTransactionRequest;
signerAddress: string;
redirectURL: string;
}
interface SignCkbRawTxRequest extends CkbDappConfig {
tx: CKBTransaction;
signerAddress: string;
redirectURL: string;
witnessIndexes?: number[];
}
interface CotaNFTTransactionRequest {
from: string;
to: string;
tokenKey?: string;
tokenId?: string;
tokenIndex?: string;
}
interface SignCotaNFTRequest extends CkbDappConfig {
tx: CotaNFTTransactionRequest;
signerAddress: string;
redirectURL: string;
}
declare enum SigningAlg {
RS256 = -257,
ES256 = -7
}
interface JoyIDConfig {
joyidAppURL?: string;
joyidServerURL?: string;
}
interface DappConfig extends JoyIDConfig {
name?: string;
logo?: string;
state?: unknown;
}
type SessionKeyType = 'main_session_key' | 'sub_session_key';
type WebauthnKeyType = 'main_key' | 'sub_key';
type CredentialKeyType = SessionKeyType | WebauthnKeyType;
type Base64URLString = string;
type RequestNetwork = 'nervos' | 'nostr' | 'ethereum' | 'btc-p2tr' | 'btc-p2wpkh' | 'btc-auto';
interface BaseRequest {
redirectURL: string;
joyidAppURL?: string;
}
type Hex$1 = `0x${string}`;
interface AuthRequest extends BaseRequest {
requestNetwork?: RequestNetwork;
name?: string;
logo?: string;
challenge?: string;
state?: unknown;
}
interface MiniAppBaseRequest {
name: string;
logo: string;
miniAppToken: string;
callbackUrl: string;
joyidAppURL?: string;
}
interface MiniAppAuthRequest extends MiniAppBaseRequest {
requestNetwork?: RequestNetwork;
challenge?: string;
}
declare enum DappRequestType {
Auth = "Auth",
SignMessage = "SignMessage",
SignEvm = "SignEvm",
SignPsbt = "SignPsbt",
BatchSignPsbt = "BatchSignPsbt",
SignCkbTx = "SignCkbTx",
SignCotaNFT = "SignCotaNFT",
SignCkbRawTx = "SignCkbRawTx",
SignNostrEvent = "SignNostrEvent",
EncryptNostrMessage = "EncryptNostrMessage",
EvmWeb2Login = "EvmWeb2Login",
DecryptNostrMessage = "DecryptNostrMessage",
AuthMiniApp = "AuthMiniApp",
SignMiniAppMessage = "SignMiniAppMessage",
SignMiniAppEvm = "SignMiniAppEvm"
}
declare enum DappCommunicationType {
Popup = "popup",
Redirect = "redirect"
}
interface SignMessageResponseData {
signature: string;
/**
* The message that was signed by the authenticator,
* Note that the message is not the original raw message,
* but is combined with client data and authenticator data
* according to [WebAuthn Spec](https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion).
*/
message: string;
/**
* The public key used to sign the message
*/
pubkey: string;
/**
* The message that was requested to be signed
*/
challenge: string;
attestation?: string;
keyType: CredentialKeyType;
alg: SigningAlg;
state?: any;
requestNetwork?: RequestNetwork;
}
interface AuthResponseData extends Partial<SignMessageResponseData> {
address: string;
ethAddress: string;
nostrPubkey: string;
pubkey: string;
challenge?: string;
message?: string;
keyType: CredentialKeyType;
alg: SigningAlg;
btcAddressType?: 'p2tr' | 'p2wpkh';
taproot: {
address: string;
pubkey: string;
};
nativeSegwit: {
address: string;
pubkey: string;
};
}
interface DappResponse<T> {
error: string;
data: T;
state?: any;
}
type AuthResponse = {
type: DappRequestType.Auth;
} & RequireExactlyOne<DappResponse<AuthResponseData>, 'data' | 'error'>;
type SignMessageResponse = {
type: DappRequestType.SignMessage;
} & RequireExactlyOne<DappResponse<SignMessageResponseData>, 'data' | 'error'>;
interface BaseSignMessageRequest extends AuthRequest {
challenge: string;
isData?: boolean;
address?: string;
requestNetwork?: RequestNetwork;
}
interface MiniAppSignMessageRequest extends MiniAppBaseRequest {
requestNetwork?: RequestNetwork;
challenge?: string;
isData?: boolean;
address: string;
}
interface SignEvmTxResponseData {
tx: Hex$1;
state?: any;
}
type SignEvmResponse = {
type: DappRequestType.SignEvm;
} & RequireExactlyOne<DappResponse<SignEvmTxResponseData>, 'data' | 'error'>;
type SignMessageRequest = RequireExactlyOne<BaseSignMessageRequest, 'address'>;
type BtcSignMessageType = 'bip322-simple' | 'ecdsa';
interface BtcSignMessageRequest extends SignMessageRequest {
signMessageType: BtcSignMessageType;
}
interface SignCkbTxResponseData {
tx: CKBTransaction;
state?: any;
}
type SignCkbTxResponse = {
type: DappRequestType.SignCkbTx;
} & RequireExactlyOne<DappResponse<SignCkbTxResponseData>, 'data' | 'error'>;
type SignCotaNFTResponseData = SignCkbTxResponseData;
type SignCotaNFTResponse = {
type: DappRequestType.SignCotaNFT;
} & RequireExactlyOne<DappResponse<SignCotaNFTResponseData>, 'data' | 'error'>;
type SignCkbRawTxResponseData = SignCkbTxResponseData;
type SignCkbRawTxResponse = {
type: DappRequestType.SignCkbRawTx;
} & RequireExactlyOne<DappResponse<SignCkbRawTxResponseData>, 'data' | 'error'>;
declare const SESSION_KEY_VER = "00";
type Hex = `0x${string}`;
type EthAddress = `0x${string}`;
type AccessList = Array<{
address: EthAddress;
storageKeys: Hex[];
}>;
interface TransactionRequest {
maxPriorityFeePerGas?: string;
maxFeePerGas?: string;
to?: string;
from?: string;
nonce?: number;
gasLimit?: string;
gasPrice?: string;
data?: string;
value?: string;
chainId?: number;
accessList?: AccessList;
customData?: Record<string, any>;
ccipReadEnabled?: boolean;
}
interface EvmChainParameter {
chainId: number;
/** The chain name. */
name: string;
/** Native currency for the chain. */
nativeCurrency: {
name: string;
symbol: string;
decimals: number;
};
rpcUrls: readonly string[];
blockExplorerUrls?: string[];
iconUrls?: string[];
}
type Network = {
name: string;
chainId: number;
} | EvmChainParameter;
interface EthNetworkConfig {
network?: Network;
rpcURL?: string;
}
type EvmConfig = EthNetworkConfig & DappConfig;
type SignEvmTxRequest = EvmConfig & {
tx: TransactionRequest;
isSend?: boolean;
signerAddress: string;
redirectURL: string;
commuType?: DappCommunicationType;
};
type SignTypedDataRequest = EvmConfig & {
signerAddress: string;
redirectURL: string;
commuType?: DappCommunicationType;
typedData: TypedDataDefinition;
};
type EvmWeb2LoginConfig = EvmConfig & {
backgroundImage?: string;
};
type EvmWeb2LoginRequest = EvmWeb2LoginConfig & {
signerAddress?: string;
redirectURL: string;
commuType?: DappCommunicationType;
};
interface EvmWeb2LoginResponse {
uid: string;
entropy: string;
}
type MiniAppSignEvmTxRequest = EvmConfig & MiniAppBaseRequest & {
tx: TransactionRequest;
signerAddress: string;
isSend?: boolean;
};
type MiniAppSignTypedDataRequest = EvmConfig & MiniAppBaseRequest & {
signerAddress: string;
typedData: TypedData;
isSend?: boolean;
};
type AASignTypedDataParams = Omit<TypedDataDefinition, 'privateKey'>;
/**
* @description Combines members of an intersection into a readable type.
*
* @see {@link https://twitter.com/mattpocockuk/status/1622730173446557697?s=20&t=NdpAcmEFXY01xkqU3KO0Mg}
* @example
* Prettify<{ a: string } & { b: string } & { c: number, d: bigint }>
* => { a: string, b: string, c: number, d: bigint }
*/
type Prettify<T> = {
[K in keyof T]: T[K];
} & {};
type TypedDataDefinition<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData, primaryTypes = typedData extends TypedData ? keyof typedData : string> = primaryType extends 'EIP712Domain' ? EIP712DomainDefinition<typedData, primaryType> : MessageDefinition<typedData, primaryType, primaryTypes>;
type MessageDefinition<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends keyof typedData = keyof typedData, primaryTypes = typedData extends TypedData ? keyof typedData : string, schema extends Record<string, unknown> = typedData extends TypedData ? TypedDataToPrimitiveTypes<typedData> : Record<string, unknown>, message = schema[primaryType extends keyof schema ? primaryType : keyof schema]> = {
types: typedData;
} & {
primaryType: primaryTypes | (primaryType extends primaryTypes ? primaryType : never);
domain?: (schema extends {
EIP712Domain: infer domain;
} ? domain : Prettify<TypedDataDomain>) | undefined;
message: Record<string, any> extends message ? Record<string, unknown> : message;
};
type EIP712DomainDefinition<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends 'EIP712Domain' = 'EIP712Domain', schema extends Record<string, unknown> = typedData extends TypedData ? TypedDataToPrimitiveTypes<typedData> : Record<string, unknown>> = {
types?: typedData | undefined;
} & {
primaryType: 'EIP712Domain' | primaryType;
domain: schema extends {
EIP712Domain: infer domain;
} ? domain : Prettify<TypedDataDomain>;
message?: never | undefined;
};
/**
* A signer that can sign messages and typed data.
*
* @template Inner - the generic type of the inner client that the signer wraps to provide functionality such as signing, etc.
*
* @var signerType - the type of the signer (e.g. local, hardware, etc.)
* @var inner - the inner client of @type {Inner}
*
* @method getAddress - get the address of the signer
* @method signMessage - sign a message
* @method signTypedData - sign typed data
*/
interface SmartAccountSigner<Inner = any> {
signerType: string;
inner: Inner;
getAddress: () => Promise<Hex>;
signMessage: (msg: Uint8Array | Hex | string) => Promise<Hex>;
signTypedData: (params: AASignTypedDataParams) => Promise<Hex>;
}
interface toSignInput {
/**
* which input to sign
*/
index: number;
/**
* (at least specify either an address or a publicKey) Which corresponding private key to use for signing
*/
address: string;
/**
* (at least specify either an address or a publicKey) Which corresponding private key to use for signing
*/
publicKey: string;
/**
* (optionals) sighashTypes
*/
sighashTypes?: number[];
/**
* (optionals) When signing and unlocking Taproot addresses, the tweakSigner is used by default for signature generation. Enabling this allows for signing with the original private key.
*/
disableTweakSigner?: boolean;
}
interface SignPsbtOptions {
/**
* whether finalize psbt after signing, default is true
*/
autoFinalized: boolean;
toSignInputs: toSignInput[];
}
interface BtcConfig extends DappConfig {
requestAddressType?: 'p2tr' | 'p2wpkh' | 'auto';
}
interface SignPsbtRequest extends DappConfig {
options?: SignPsbtOptions;
signerAddress: string;
tx: string;
redirectURL: string;
commuType?: DappCommunicationType;
isSend?: boolean;
}
interface BatchSignPsbtRequest extends DappConfig {
options?: SignPsbtOptions[];
signerAddress: string;
psbts: string[];
redirectURL: string;
commuType?: DappCommunicationType;
isSend?: boolean;
}
/** @deprecated Use numbers instead. */
declare enum EventKind {
Metadata = 0,
Text = 1,
RecommendRelay = 2,
Contacts = 3,
EncryptedDirectMessage = 4,
EventDeletion = 5,
Repost = 6,
Reaction = 7,
BadgeAward = 8,
ChannelCreation = 40,
ChannelMetadata = 41,
ChannelMessage = 42,
ChannelHideMessage = 43,
ChannelMuteUser = 44,
Blank = 255,
Report = 1984,
ZapRequest = 9734,
Zap = 9735,
RelayList = 10002,
ClientAuth = 22242,
HttpAuth = 27235,
ProfileBadge = 30008,
BadgeDefinition = 30009,
Article = 30023
}
interface EventTemplate<K extends number = number> {
kind: K;
tags: string[][];
content: string;
created_at: number;
}
type UnsignedEvent<K extends number = number> = EventTemplate<K> & {
pubkey: string;
};
type Event<K extends number = number> = UnsignedEvent<K> & {
id: string;
sig: string;
};
interface GetPublicKeyRequest extends JoyIDConfig {
redirectURL: string;
name?: string;
logo?: string;
}
interface SignNostrEventRequest extends GetPublicKeyRequest {
event: UnsignedEvent<number>;
}
interface SignNostrEventData {
event: Event<number>;
}
type SignNostrEventResponse = {
type: DappRequestType.SignNostrEvent;
} & RequireExactlyOne<DappResponse<SignNostrEventData>, 'data' | 'error'>;
interface PopupConfigOptions<T extends DappRequestType = DappRequestType.Auth> {
/**
* The number of seconds to wait for a popup response before
* throwing a timeout error. Defaults to 300s
*/
timeoutInSeconds?: number;
/**
* Accepts an already-created popup window to use. If not specified, the SDK
* will create its own. This may be useful for platforms like iOS that have
* security restrictions around when popups can be invoked (e.g. from a user click event)
*/
popup?: any;
type: T;
}
declare const openPopup: (url?: string) => Window | null;
interface PopupRerurnType {
[DappRequestType.Auth]: AuthResponseData;
[DappRequestType.SignMessage]: SignMessageResponseData;
[DappRequestType.SignEvm]: SignEvmTxResponseData;
[DappRequestType.SignPsbt]: SignEvmTxResponseData;
[DappRequestType.BatchSignPsbt]: {
psbts: string[];
};
[DappRequestType.SignCkbTx]: SignCkbTxResponseData;
[DappRequestType.SignCotaNFT]: SignCotaNFTResponseData;
[DappRequestType.SignCkbRawTx]: SignCkbTxResponseData;
[DappRequestType.SignNostrEvent]: SignNostrEventData;
[DappRequestType.EncryptNostrMessage]: any;
[DappRequestType.DecryptNostrMessage]: any;
[DappRequestType.AuthMiniApp]: any;
[DappRequestType.SignMiniAppEvm]: any;
[DappRequestType.SignMiniAppMessage]: any;
[DappRequestType.EvmWeb2Login]: EvmWeb2LoginResponse;
}
declare const runPopup: <T extends DappRequestType>(config: PopupConfigOptions<T> & Partial<DappConfig>) => Promise<PopupRerurnType[T]>;
declare const buildJoyIDAuthURL: (request: AuthRequest, type: 'popup' | 'redirect') => string;
declare const authWithRedirect: (request: AuthRequest) => void;
declare const authWithPopup: (request: AuthRequest, config?: Pick<PopupConfigOptions, 'timeoutInSeconds' | 'popup'>) => Promise<AuthResponseData>;
declare const authCallback: (uri?: string) => AuthResponseData;
declare const appendStyle: () => void;
declare const createBlockDialog: <T>(cb: (...args: any[]) => Promise<T>) => Promise<T>;
declare const internalConfig: DappConfig;
declare const initConfig: (config?: DappConfig) => DappConfig;
declare const getConfig: () => DappConfig;
declare class GenericError extends Error {
error: string;
error_description: string;
constructor(error: string, error_description: string);
}
declare class TimeoutError extends GenericError {
constructor();
}
/**
* Error thrown when the login popup times out (if the user does not complete auth)
*/
declare class PopupTimeoutError extends TimeoutError {
popup: Window;
constructor(popup: Window);
}
declare class PopupCancelledError extends GenericError {
popup?: Window | undefined;
constructor(popup?: Window | undefined);
}
declare class PopupNotSupportedError extends GenericError {
popup: Window;
constructor(popup: Window);
}
declare class RedirectErrorWithState extends Error {
message: string;
state?: any;
constructor(message: string, state?: any);
}
declare const getRedirectResponse: <T extends {
state?: any;
}>(uri?: string) => T;
declare const buildJoyIDURL: <T extends BaseRequest>(request: T, type: 'popup' | 'redirect', path: string) => string;
declare const isRedirectFromJoyID: (uri?: string) => boolean;
declare const buildJoyIDSignMessageURL: (request: SignMessageRequest & Record<string, unknown>, type: 'redirect' | 'popup') => string;
declare const signMessageWithRedirect: (request: SignMessageRequest) => void;
declare const signMessageWithPopup: <T extends DappRequestType>(request: SignMessageRequest & Record<string, unknown>, config?: Pick<PopupConfigOptions<T>, "popup" | "timeoutInSeconds"> | undefined) => Promise<SignMessageResponseData>;
declare const signMessageCallback: (uri?: string) => SignMessageResponseData;
export { AASignTypedDataParams, AccessList, AuthRequest, AuthResponse, AuthResponseData, Base64URLString, BaseRequest, BaseSignMessageRequest, BatchSignPsbtRequest, BtcConfig, BtcSignMessageRequest, BtcSignMessageType, CKBTransaction, CellDep, CkbDappConfig, CkbTransactionRequest, CotaNFTTransactionRequest, CredentialKeyType, DappCommunicationType, DappConfig, DappError, DappErrorName, DappRequestType, DappResponse, DepType, EthAddress, EthNetworkConfig, Event, EventKind, EventTemplate, EvmChainParameter, EvmConfig, EvmWeb2LoginConfig, EvmWeb2LoginRequest, EvmWeb2LoginResponse, GenericError, GetPublicKeyRequest, Hash, HashType, Header, Hex, HexNumber, HexString, Input, JoyIDConfig, MiniAppAuthRequest, MiniAppBaseRequest, MiniAppSignEvmTxRequest, MiniAppSignMessageRequest, MiniAppSignTypedDataRequest, Network, OutPoint, Output, PackedSince, PopupCancelledError, PopupConfigOptions, PopupNotSupportedError, PopupRerurnType, PopupTimeoutError, Prettify, RawTransaction, RedirectErrorWithState, RequestNetwork, SESSION_KEY_VER, Script, SessionKeyType, SignCkbRawTxRequest, SignCkbRawTxResponse, SignCkbRawTxResponseData, SignCkbTxRequest, SignCkbTxResponse, SignCkbTxResponseData, SignCotaNFTRequest, SignCotaNFTResponse, SignCotaNFTResponseData, SignEvmResponse, SignEvmTxRequest, SignEvmTxResponseData, SignMessageRequest, SignMessageResponse, SignMessageResponseData, SignNostrEventData, SignNostrEventRequest, SignNostrEventResponse, SignPsbtOptions, SignPsbtRequest, SignTypedDataRequest, SigningAlg, SmartAccountSigner, TimeoutError, TransactionRequest, TypedDataDefinition, UnsignedEvent, WebauthnKeyType, WitnessArgs, append0x, appendBuffer, appendStyle, authCallback, authWithPopup, authWithRedirect, base64URLStringToBuffer, base64urlToHex, bufferToBase64URLString, bufferToHex, bufferToUTF8String, buildJoyIDAuthURL, buildJoyIDSignMessageURL, buildJoyIDURL, createBlockDialog, decodeSearch, encodeSearch, getConfig, getRedirectResponse, hexToArrayBuffer, hexToString, hexToUTF8String, initConfig, internalConfig, isRedirectFromJoyID, isStandaloneBrowser, openPopup, parseSearchWith, remove0x, runPopup, safeExec, signMessageCallback, signMessageWithPopup, signMessageWithRedirect, stringifySearchWith, toSignInput, utf8StringToBuffer };