rebrand(lethean): update branding, ports, and config for Lethean blockchain
Some checks failed
Deploy LetheanCompanion Test Suit to Github Pages / Build and Deploy (push) Failing after 4s
Some checks failed
Deploy LetheanCompanion Test Suit to Github Pages / Build and Deploy (push) Failing after 4s
- Coin: Zano → Lethean, ticker: ZAN/ZANO → LTHN - Ports: 11211 → 36941 (mainnet RPC), 46941 (testnet RPC) - Wallet: 11212 → 36944/46944 - Address prefix: iTHN - URLs: zano.org → lethean.io - Explorer links: explorer.lthn.io Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fcffea241d
commit
e25e773fc9
28 changed files with 144 additions and 119 deletions
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: "Deploy ZanoCompanion Test Suit to Github Pages"
|
||||
name: "Deploy LetheanCompanion Test Suit to Github Pages"
|
||||
|
||||
on:
|
||||
push:
|
||||
|
|
|
|||
25
Dockerfile
Normal file
25
Dockerfile
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Build + serve: compiles the React/Vite test harness and serves on port 5173
|
||||
FROM node:22-alpine AS builder
|
||||
|
||||
# pnpm is the declared package manager
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
COPY . .
|
||||
RUN pnpm run build
|
||||
|
||||
# Serve the static dist with a minimal HTTP server
|
||||
FROM node:22-alpine
|
||||
|
||||
RUN npm install -g serve
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /app/dist ./dist
|
||||
|
||||
EXPOSE 5173
|
||||
CMD ["serve", "-s", "dist", "-l", "5173"]
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/png" href="/favicon.png" sizes="96x96" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>zano-companion-testsuit</title>
|
||||
<title>lethean-companion-testsuit</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "zano-companion-testsuit",
|
||||
"name": "lethean-companion-testsuit",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { useCallback, useState } from "react";
|
||||
import type { ASSETS_WHITELIST_ADD_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
import { particlesToValue } from "./utils";
|
||||
|
||||
export const AddWhitelist = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [response, setResponse] = useState<ASSETS_WHITELIST_ADD_RESPONSE | string | null>(null);
|
||||
const call = useCallback(async () => {
|
||||
const asset_id = prompt("What asset do you want to add?");
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useCallback, useState } from "react";
|
||||
import type { GET_ALIAS_DETAILS_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
export const AliasDetails = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [details, setDetails] = useState<GET_ALIAS_DETAILS_RESPONSE | string | null>(null);
|
||||
const fetchDetails = useCallback(async () => {
|
||||
let alias = prompt("What alias are you searching for?");
|
||||
|
|
|
|||
12
src/App.tsx
12
src/App.tsx
|
|
@ -1,7 +1,7 @@
|
|||
import "./app.css";
|
||||
|
||||
import { AliasDetails } from "./AliasDetails";
|
||||
import { ZanoCompanionProvider } from "./companion";
|
||||
import { LetheanCompanionProvider } from "./companion";
|
||||
import { Connector } from "./Connector";
|
||||
import { CreateAlias } from "./CreateAlias";
|
||||
import { Credentials } from "./Credentials";
|
||||
|
|
@ -16,17 +16,17 @@ import { Transfer } from "./Transfer";
|
|||
import { WalletBalance } from "./WalletBalance";
|
||||
import { WalletData } from "./WalletData";
|
||||
import { Whitelist } from "./Whitelist";
|
||||
import ZanoLogo from "./zano.svg";
|
||||
import LetheanLogo from "./lethean.svg";
|
||||
|
||||
export const App = () => {
|
||||
return (
|
||||
<div id="screen">
|
||||
<div id="header">
|
||||
<img src={ZanoLogo} className="logo" alt="Zano logo" />
|
||||
<span>ZanoCompanion Test Suits</span>
|
||||
<img src={LetheanLogo} className="logo" alt="Lethean logo" />
|
||||
<span>LetheanCompanion Test Suits</span>
|
||||
</div>
|
||||
<div id="content">
|
||||
<ZanoCompanionProvider disableServerRequest verbose>
|
||||
<LetheanCompanionProvider disableServerRequest verbose>
|
||||
<div>Links</div>
|
||||
<DeepLinkTransfer />
|
||||
<DeepLinkTransferLegacy />
|
||||
|
|
@ -45,7 +45,7 @@ export const App = () => {
|
|||
<RequestSign />
|
||||
<AliasDetails />
|
||||
<CreateAlias />
|
||||
</ZanoCompanionProvider>
|
||||
</LetheanCompanionProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useZanoCompanionConnect } from "./companion";
|
||||
import { useLetheanCompanionConnect } from "./companion";
|
||||
|
||||
export const Connector = () => {
|
||||
const [status, connect, disconnect] = useZanoCompanionConnect();
|
||||
const [status, connect, disconnect] = useLetheanCompanionConnect();
|
||||
return (
|
||||
<button onClick={status === "disconnected" ? connect : status === "connected" ? disconnect : undefined} disabled={status === "pending"}>
|
||||
connection state: {status}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useCallback, useState } from "react";
|
||||
import type { CREATE_ALIAS_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
export const CreateAlias = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [response, setResponse] = useState<CREATE_ALIAS_RESPONSE | string | null>(null);
|
||||
const call = useCallback(async () => {
|
||||
let alias = prompt("What alias do you want to create?");
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useZanoCompanionCredentials } from "./companion";
|
||||
import { useLetheanCompanionCredentials } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
export const Credentials = () => {
|
||||
const credentials = useZanoCompanionCredentials();
|
||||
const credentials = useLetheanCompanionCredentials();
|
||||
if (!credentials) return null;
|
||||
return (
|
||||
<Group>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const DeepLinkTransfer = () => {
|
|||
const amount = BigNumber(prompt("How many?") ?? NaN);
|
||||
const comment = prompt("Comment:") ?? undefined;
|
||||
setLink(
|
||||
`zano://transfer/?address=${address}${assetId ? `&asset_id=${assetId}` : ""}${amount.isNaN() ? "" : `&amount=${amount.toString(10)}`}${comment ? `&comment=${comment}` : ""}`,
|
||||
`lthn://transfer/?address=${address}${assetId ? `&asset_id=${assetId}` : ""}${amount.isNaN() ? "" : `&amount=${amount.toString(10)}`}${comment ? `&comment=${comment}` : ""}`,
|
||||
);
|
||||
}, []);
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const DeepLinkTransferLegacy = () => {
|
|||
const amount = BigNumber(prompt("How many?") ?? NaN);
|
||||
const comment = prompt("Comment:") ?? undefined;
|
||||
setLink(
|
||||
`zano:action=send&address=${address}${assetId ? `&asset_id=${assetId}` : ""}${amount.isNaN() ? "" : `&amount=${amount.toString(10)}`}${comment ? `&comment=${comment}` : ""}`,
|
||||
`lthn://transfer/?action=send&address=${address}${assetId ? `&asset_id=${assetId}` : ""}${amount.isNaN() ? "" : `&amount=${amount.toString(10)}`}${comment ? `&comment=${comment}` : ""}`,
|
||||
);
|
||||
}, []);
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { BigNumber } from "bignumber.js";
|
||||
import { useCallback, useState } from "react";
|
||||
import type { IONIC_SWAP_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
export const IonicSwap = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [response, setResponse] = useState<IONIC_SWAP_RESPONSE | string | null>(null);
|
||||
const call = useCallback(async () => {
|
||||
const destinationAddress = prompt("With whom do you swaping?");
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useCallback, useState } from "react";
|
||||
import type { IONIC_SWAP_ACCEPT_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
export const IonicSwapAccept = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [response, setResponse] = useState<IONIC_SWAP_ACCEPT_RESPONSE | string | null>(null);
|
||||
const call = useCallback(async () => {
|
||||
const hex_raw_proposal = prompt("What proposal you want to accept?");
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { useCallback, useState } from "react";
|
||||
import type { GET_IONIC_SWAP_PROPOSAL_INFO_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
import { particlesToValue } from "./utils";
|
||||
|
||||
export const IonicSwapInfo = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [response, setResponse] = useState<GET_IONIC_SWAP_PROPOSAL_INFO_RESPONSE | string | null>(null);
|
||||
const call = useCallback(async () => {
|
||||
const hex_raw_proposal = prompt("What proposal you want to inspect?");
|
||||
|
|
@ -48,7 +48,7 @@ export const IonicSwapInfo = () => {
|
|||
))}
|
||||
<span>Additional fields:</span>
|
||||
<Group>
|
||||
<Group.Item label="Fee:" value={`${particlesToValue(response.proposal.fee_paid_by_a, 12)} ZANO`} />
|
||||
<Group.Item label="Fee:" value={`${particlesToValue(response.proposal.fee_paid_by_a, 12)} LTHN`} />
|
||||
</Group>
|
||||
</>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { BigNumber } from "bignumber.js";
|
||||
import { useCallback, useState } from "react";
|
||||
import type { TRANSFER_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
export const MultiTransfer = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [response, setResponse] = useState<TRANSFER_RESPONSE | string | null>(null);
|
||||
const call = useCallback(async () => {
|
||||
const destinations: { address: string; amount: string; assetId?: string }[] = [];
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useCallback, useState } from "react";
|
||||
import type { REQUEST_MESSAGE_SIGN_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
export const RequestSign = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [response, setResponse] = useState<REQUEST_MESSAGE_SIGN_RESPONSE | string | null>(null);
|
||||
const call = useCallback(async () => {
|
||||
const message = prompt("What message are you trying to sign?");
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { BigNumber } from "bignumber.js";
|
||||
import { useCallback, useState } from "react";
|
||||
import type { TRANSFER_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
export const Transfer = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const [response, setResponse] = useState<TRANSFER_RESPONSE | string | null>(null);
|
||||
const call = useCallback(async () => {
|
||||
const destination = prompt("Whom do you send it?");
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { useCallback, useRef, useState, useSyncExternalStore } from "react";
|
||||
import type { GET_WALLET_BALANCE_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
import { particlesToValue } from "./utils";
|
||||
|
||||
const WalletBalanceWatcher = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const snapshot = useRef<GET_WALLET_BALANCE_RESPONSE | null>(null);
|
||||
const response = useSyncExternalStore(
|
||||
useCallback(
|
||||
|
|
@ -25,8 +25,8 @@ const WalletBalanceWatcher = () => {
|
|||
return (
|
||||
<>
|
||||
<Group>
|
||||
<Group.Item label="Balance:" value={`${particlesToValue(response?.balance ?? 0, 12)} ZANO`} />
|
||||
<Group.Item label="Unlocked Balance:" value={`${particlesToValue(response?.unlocked_balance ?? 0, 12)} ZANO`} />
|
||||
<Group.Item label="Balance:" value={`${particlesToValue(response?.balance ?? 0, 12)} LTHN`} />
|
||||
<Group.Item label="Unlocked Balance:" value={`${particlesToValue(response?.unlocked_balance ?? 0, 12)} LTHN`} />
|
||||
</Group>
|
||||
<Group>
|
||||
{response?.balances.map((balance) => (
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useCallback, useRef, useState, useSyncExternalStore } from "react";
|
||||
import type { GET_WALLET_DATA_RESPONSE } from "./companion";
|
||||
import { useZanoCompanion } from "./companion";
|
||||
import { useLetheanCompanion } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
const WalletDataWatcher = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const snapshot = useRef<GET_WALLET_DATA_RESPONSE | null>(null);
|
||||
const walletData = useSyncExternalStore(
|
||||
useCallback(
|
||||
|
|
@ -22,7 +22,7 @@ const WalletDataWatcher = () => {
|
|||
return (
|
||||
<Group>
|
||||
{walletData?.alias ? <Group.Item label="Alias:" value={`@${walletData.alias}`} /> : null}
|
||||
<Group.Item label="Balance:" value={`${walletData?.balance} ZANO`} />
|
||||
<Group.Item label="Balance:" value={`${walletData?.balance} LTHN`} />
|
||||
</Group>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { useCallback, useRef, useState, useSyncExternalStore } from "react";
|
||||
import { useZanoCompanion, type GET_WHITELIST_RESPONSE } from "./companion";
|
||||
import { useLetheanCompanion, type GET_WHITELIST_RESPONSE } from "./companion";
|
||||
import { Group } from "./Group";
|
||||
|
||||
const WhitelistWatcher = () => {
|
||||
const companion = useZanoCompanion();
|
||||
const companion = useLetheanCompanion();
|
||||
const snapshot = useRef<GET_WHITELIST_RESPONSE | null>(null);
|
||||
const response = useSyncExternalStore(
|
||||
useCallback(
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
import { v4 as uuidv4 } from "uuid";
|
||||
import { ZanoCredentials, type ZanoCredentialsParams } from "./credentials";
|
||||
import type { ZanoCompanionMethodParams, ZanoCompanionMethodResult, ZanoCompanionMethods } from "./types";
|
||||
import { LetheanCredentials, type LetheanCredentialsParams } from "./credentials";
|
||||
import type { LetheanCompanionMethodParams, LetheanCompanionMethodResult, LetheanCompanionMethods } from "./types";
|
||||
|
||||
declare global {
|
||||
interface ZanoCompanionApi {
|
||||
request<Method extends keyof ZanoCompanionMethods>(
|
||||
interface LetheanCompanionApi {
|
||||
request<Method extends keyof LetheanCompanionMethods>(
|
||||
method: Method,
|
||||
...params: keyof ZanoCompanionMethodParams<Method> extends undefined
|
||||
? [params?: ZanoCompanionMethodParams<Method>, timeoutMs?: number | null]
|
||||
: [params: ZanoCompanionMethodParams<Method>, timeoutMs?: number | null]
|
||||
): Promise<{ data: ZanoCompanionMethodResult<Method> } | undefined>;
|
||||
...params: keyof LetheanCompanionMethodParams<Method> extends undefined
|
||||
? [params?: LetheanCompanionMethodParams<Method>, timeoutMs?: number | null]
|
||||
: [params: LetheanCompanionMethodParams<Method>, timeoutMs?: number | null]
|
||||
): Promise<{ data: LetheanCompanionMethodResult<Method> } | undefined>;
|
||||
}
|
||||
var zano: ZanoCompanionApi | undefined;
|
||||
var lethean: LetheanCompanionApi | undefined;
|
||||
}
|
||||
|
||||
export type ZanoCompanionServerData = {
|
||||
export type LetheanCompanionServerData = {
|
||||
alias: string | undefined;
|
||||
address: string;
|
||||
signature: string;
|
||||
|
|
@ -22,40 +22,40 @@ export type ZanoCompanionServerData = {
|
|||
message: string;
|
||||
isSavedData: boolean | undefined;
|
||||
};
|
||||
export type ZanoCompanionParams = ZanoCredentialsParams & {
|
||||
export type LetheanCompanionParams = LetheanCredentialsParams & {
|
||||
aliasRequired?: boolean;
|
||||
customNonce?: string;
|
||||
customServerPath?: string;
|
||||
disableServerRequest?: boolean;
|
||||
|
||||
onConnectStart?: () => void;
|
||||
onConnectEnd?: (data: ZanoCompanionServerData & { token: string }) => void;
|
||||
onLocalConnectEnd?: (data: ZanoCompanionServerData) => void;
|
||||
onConnectEnd?: (data: LetheanCompanionServerData & { token: string }) => void;
|
||||
onLocalConnectEnd?: (data: LetheanCompanionServerData) => void;
|
||||
|
||||
verbose?: boolean;
|
||||
};
|
||||
|
||||
type AuthServerResponse = { success: true; data: { token: string } } | { success: false; error: string };
|
||||
|
||||
type UnwrappedZanoCompanionMethodResult<Method extends keyof ZanoCompanionMethods> = Exclude<ZanoCompanionMethodResult<Method>, { error: unknown }>;
|
||||
export class ZanoCompanion {
|
||||
#params: ZanoCompanionParams;
|
||||
type UnwrappedLetheanCompanionMethodResult<Method extends keyof LetheanCompanionMethods> = Exclude<LetheanCompanionMethodResult<Method>, { error: unknown }>;
|
||||
export class LetheanCompanion {
|
||||
#params: LetheanCompanionParams;
|
||||
readonly methods: {
|
||||
[Method in keyof ZanoCompanionMethods]: (
|
||||
...params: keyof ZanoCompanionMethodParams<Method> extends undefined
|
||||
? [params?: ZanoCompanionMethodParams<Method>, timeoutMs?: number | null]
|
||||
: [params: ZanoCompanionMethodParams<Method>, timeoutMs?: number | null]
|
||||
) => Promise<UnwrappedZanoCompanionMethodResult<Method>>;
|
||||
[Method in keyof LetheanCompanionMethods]: (
|
||||
...params: keyof LetheanCompanionMethodParams<Method> extends undefined
|
||||
? [params?: LetheanCompanionMethodParams<Method>, timeoutMs?: number | null]
|
||||
: [params: LetheanCompanionMethodParams<Method>, timeoutMs?: number | null]
|
||||
) => Promise<UnwrappedLetheanCompanionMethodResult<Method>>;
|
||||
};
|
||||
readonly credentials: ZanoCredentials;
|
||||
readonly credentials: LetheanCredentials;
|
||||
|
||||
constructor(params: ZanoCompanionParams) {
|
||||
constructor(params: LetheanCompanionParams) {
|
||||
if (typeof window === "undefined") {
|
||||
throw new Error("ZanoWallet can only be used in the browser");
|
||||
throw new Error("LetheanWallet can only be used in the browser");
|
||||
}
|
||||
|
||||
if (!window.zano) {
|
||||
console.error("ZanoWallet requires the ZanoWallet extension to be installed");
|
||||
if (!window.lethean) {
|
||||
console.error("LetheanWallet requires the LetheanWallet extension to be installed");
|
||||
}
|
||||
|
||||
this.#params = Object.freeze(params);
|
||||
|
|
@ -64,21 +64,21 @@ export class ZanoCompanion {
|
|||
const credentials = this.credentials.get();
|
||||
if (credentials && result.address !== credentials?.address) this.credentials.clear();
|
||||
},
|
||||
} as { [Method in keyof ZanoCompanionMethods]?: (result: UnwrappedZanoCompanionMethodResult<Method>) => void };
|
||||
} as { [Method in keyof LetheanCompanionMethods]?: (result: UnwrappedLetheanCompanionMethodResult<Method>) => void };
|
||||
|
||||
this.methods = new Proxy(
|
||||
{},
|
||||
{
|
||||
get: (cache, prop) => {
|
||||
const method = prop as keyof ZanoCompanionMethods;
|
||||
const method = prop as keyof LetheanCompanionMethods;
|
||||
// @ts-expect-error - untyped
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
if (cache[method]) return cache[method];
|
||||
// @ts-expect-error - untyped
|
||||
cache[method] = async (params: Parameters<ZanoCompanionMethods[typeof method]>[0], timeoutMs?: number | null) => {
|
||||
if (!window.zano) throw new Error("ZanoWallet requires the ZanoWallet extension to be installed");
|
||||
cache[method] = async (params: Parameters<LetheanCompanionMethods[typeof method]>[0], timeoutMs?: number | null) => {
|
||||
if (!window.lethean) throw new Error("LetheanWallet requires the LetheanWallet extension to be installed");
|
||||
if (this.#params.verbose) console.info(`> call ${method} with`, params);
|
||||
const response = await window.zano.request(method, params, timeoutMs).catch((reason) => {
|
||||
const response = await window.lethean.request(method, params, timeoutMs).catch((reason) => {
|
||||
if (this.#params.verbose) console.info(`> ${method} throws`, reason);
|
||||
throw reason;
|
||||
});
|
||||
|
|
@ -98,7 +98,7 @@ export class ZanoCompanion {
|
|||
},
|
||||
) as never;
|
||||
|
||||
this.credentials = new ZanoCredentials(params);
|
||||
this.credentials = new LetheanCredentials(params);
|
||||
}
|
||||
|
||||
async connect(signal?: AbortSignal) {
|
||||
|
|
@ -132,7 +132,7 @@ export class ZanoCompanion {
|
|||
publicKey = signResult.result.pkey;
|
||||
}
|
||||
|
||||
const serverData: ZanoCompanionServerData = {
|
||||
const serverData: LetheanCompanionServerData = {
|
||||
alias: walletData.alias,
|
||||
address: walletData.address,
|
||||
signature,
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
export interface IZanoCredentials {
|
||||
export interface ILetheanCredentials {
|
||||
nonce: string;
|
||||
signature: string;
|
||||
publicKey: string;
|
||||
address: string;
|
||||
}
|
||||
|
||||
export type ZanoCredentialsParams = {
|
||||
export type LetheanCredentialsParams = {
|
||||
useLocalStorage?: boolean;
|
||||
customLocalStorageKey?: string;
|
||||
};
|
||||
|
||||
export class ZanoCredentials {
|
||||
export class LetheanCredentials {
|
||||
static readonly #DEFAULT_LOCAL_STORAGE_KEY = "wallet";
|
||||
#localStorageKey: string | false;
|
||||
|
||||
constructor({ useLocalStorage = true, customLocalStorageKey }: ZanoCredentialsParams = {}) {
|
||||
this.#localStorageKey = useLocalStorage ? (customLocalStorageKey ?? ZanoCredentials.#DEFAULT_LOCAL_STORAGE_KEY) : false;
|
||||
constructor({ useLocalStorage = true, customLocalStorageKey }: LetheanCredentialsParams = {}) {
|
||||
this.#localStorageKey = useLocalStorage ? (customLocalStorageKey ?? LetheanCredentials.#DEFAULT_LOCAL_STORAGE_KEY) : false;
|
||||
}
|
||||
|
||||
#stored: IZanoCredentials | null = null;
|
||||
#stored: ILetheanCredentials | null = null;
|
||||
restore(address?: string) {
|
||||
let next = (() => {
|
||||
if (!this.#localStorageKey) return null;
|
||||
const json = localStorage.getItem(this.#localStorageKey);
|
||||
if (json === null) return null;
|
||||
try {
|
||||
const parsed = JSON.parse(json) as IZanoCredentials;
|
||||
const parsed = JSON.parse(json) as ILetheanCredentials;
|
||||
return parsed;
|
||||
} catch {
|
||||
return null;
|
||||
|
|
@ -46,7 +46,7 @@ export class ZanoCredentials {
|
|||
if (this.#localStorageKey) localStorage.removeItem(this.#localStorageKey);
|
||||
void this.emit(null);
|
||||
}
|
||||
set(credentials: IZanoCredentials | null) {
|
||||
set(credentials: ILetheanCredentials | null) {
|
||||
this.#stored = credentials;
|
||||
if (this.#localStorageKey) {
|
||||
if (credentials) localStorage.setItem(this.#localStorageKey, JSON.stringify(credentials));
|
||||
|
|
@ -55,18 +55,18 @@ export class ZanoCredentials {
|
|||
void this.emit(credentials);
|
||||
}
|
||||
|
||||
private listeners = new Set<(credentials: IZanoCredentials | null) => void>();
|
||||
private async emit(credentials: IZanoCredentials | null) {
|
||||
private listeners = new Set<(credentials: ILetheanCredentials | null) => void>();
|
||||
private async emit(credentials: ILetheanCredentials | null) {
|
||||
await Promise.resolve();
|
||||
this.listeners.forEach((listener) => listener(credentials));
|
||||
}
|
||||
addListener(listener: (credentials: IZanoCredentials | null) => void) {
|
||||
addListener(listener: (credentials: ILetheanCredentials | null) => void) {
|
||||
this.listeners.add(listener);
|
||||
return () => {
|
||||
this.listeners.delete(listener);
|
||||
};
|
||||
}
|
||||
removeListener(listener: (credentials: IZanoCredentials | null) => void) {
|
||||
removeListener(listener: (credentials: ILetheanCredentials | null) => void) {
|
||||
this.listeners.delete(listener);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { createContext, useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore, type ReactNode } from "react";
|
||||
import { assert } from "../utils";
|
||||
import { ZanoCompanion, type ZanoCompanionParams } from "./companion";
|
||||
import { LetheanCompanion, type LetheanCompanionParams } from "./companion";
|
||||
|
||||
export const useZanoCompanionInstance = ({ onConnectStart, onConnectEnd, onLocalConnectEnd, ...params }: ZanoCompanionParams = {}) => {
|
||||
export const useLetheanCompanionInstance = ({ onConnectStart, onConnectEnd, onLocalConnectEnd, ...params }: LetheanCompanionParams = {}) => {
|
||||
const onConnectStartRef = useRef(onConnectStart);
|
||||
onConnectStartRef.current = onConnectStart;
|
||||
const onConnectEndRef = useRef(onConnectEnd);
|
||||
|
|
@ -10,9 +10,9 @@ export const useZanoCompanionInstance = ({ onConnectStart, onConnectEnd, onLocal
|
|||
const onLocalConnectEndRef = useRef(onLocalConnectEnd);
|
||||
onLocalConnectEndRef.current = onLocalConnectEnd;
|
||||
|
||||
const instance = useRef<ZanoCompanion | null>(null);
|
||||
const instance = useRef<LetheanCompanion | null>(null);
|
||||
if (!instance.current) {
|
||||
instance.current = new ZanoCompanion({
|
||||
instance.current = new LetheanCompanion({
|
||||
...params,
|
||||
onConnectStart: (...params) => onConnectStartRef.current?.(...params),
|
||||
onConnectEnd: (...params) => onConnectEndRef.current?.(...params),
|
||||
|
|
@ -23,20 +23,20 @@ export const useZanoCompanionInstance = ({ onConnectStart, onConnectEnd, onLocal
|
|||
return instance.current;
|
||||
};
|
||||
|
||||
const ZanoCompanionContext = createContext<ZanoCompanion | undefined>(undefined);
|
||||
export const ZanoCompanionProvider = ({ children, ...params }: { children?: ReactNode } & ZanoCompanionParams) => {
|
||||
const companion = useZanoCompanionInstance(params);
|
||||
return <ZanoCompanionContext.Provider value={companion}>{children}</ZanoCompanionContext.Provider>;
|
||||
const LetheanCompanionContext = createContext<LetheanCompanion | undefined>(undefined);
|
||||
export const LetheanCompanionProvider = ({ children, ...params }: { children?: ReactNode } & LetheanCompanionParams) => {
|
||||
const companion = useLetheanCompanionInstance(params);
|
||||
return <LetheanCompanionContext.Provider value={companion}>{children}</LetheanCompanionContext.Provider>;
|
||||
};
|
||||
export const useZanoCompanion = (companion?: ZanoCompanion) => {
|
||||
const context = useContext(ZanoCompanionContext);
|
||||
export const useLetheanCompanion = (companion?: LetheanCompanion) => {
|
||||
const context = useContext(LetheanCompanionContext);
|
||||
if (!companion) companion = context;
|
||||
assert(companion, "component must be wrapped in <ZanoCompanionProvider />");
|
||||
assert(companion, "component must be wrapped in <LetheanCompanionProvider />");
|
||||
return companion;
|
||||
};
|
||||
|
||||
export const useZanoCompanionCredentials = (companion?: ZanoCompanion) => {
|
||||
companion = useZanoCompanion(companion);
|
||||
export const useLetheanCompanionCredentials = (companion?: LetheanCompanion) => {
|
||||
companion = useLetheanCompanion(companion);
|
||||
const credentials = useSyncExternalStore(
|
||||
useCallback((listener) => companion.credentials.addListener(listener), [companion.credentials]),
|
||||
() => companion.credentials.get(),
|
||||
|
|
@ -44,8 +44,8 @@ export const useZanoCompanionCredentials = (companion?: ZanoCompanion) => {
|
|||
return credentials;
|
||||
};
|
||||
|
||||
export const useZanoCompanionConnect = (companion?: ZanoCompanion) => {
|
||||
companion = useZanoCompanion(companion);
|
||||
export const useLetheanCompanionConnect = (companion?: LetheanCompanion) => {
|
||||
companion = useLetheanCompanion(companion);
|
||||
const [status, setStatus] = useState<"disconnected" | "pending" | "connected">("disconnected");
|
||||
const statusRef = useRef(status);
|
||||
statusRef.current = status;
|
||||
|
|
@ -81,9 +81,9 @@ export const useZanoCompanionConnect = (companion?: ZanoCompanion) => {
|
|||
return [status, connect, disconnect] as const;
|
||||
};
|
||||
|
||||
export const useZanoCompanionConnectEffect = (companion?: ZanoCompanion) => {
|
||||
const [state, connect, disconnect] = useZanoCompanionConnect(companion);
|
||||
const credentials = useZanoCompanionCredentials(companion);
|
||||
export const useLetheanCompanionConnectEffect = (companion?: LetheanCompanion) => {
|
||||
const [state, connect, disconnect] = useLetheanCompanionConnect(companion);
|
||||
const credentials = useLetheanCompanionCredentials(companion);
|
||||
useEffect(() => {
|
||||
const abort = connect();
|
||||
return () => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export * from "./companion";
|
||||
export type { IZanoCredentials } from "./credentials";
|
||||
export type { ILetheanCredentials } from "./credentials";
|
||||
export * from "./hooks";
|
||||
export * from "./types";
|
||||
|
|
|
|||
|
|
@ -128,9 +128,9 @@ export type ASSETS_WHITELIST_ADD_RESPONSE = {
|
|||
asset_descriptor: asset_descriptor_with_id;
|
||||
};
|
||||
|
||||
export type ZanoCompanionWrappedMethod<Result> = { result: Result; error?: undefined } | { result?: undefined; error: unknown };
|
||||
export type ZanoCompanionMethods = {
|
||||
GET_WALLET_BALANCE(params?: Record<string, never>): ZanoCompanionWrappedMethod<GET_WALLET_BALANCE_RESPONSE>;
|
||||
export type LetheanCompanionWrappedMethod<Result> = { result: Result; error?: undefined } | { result?: undefined; error: unknown };
|
||||
export type LetheanCompanionMethods = {
|
||||
GET_WALLET_BALANCE(params?: Record<string, never>): LetheanCompanionWrappedMethod<GET_WALLET_BALANCE_RESPONSE>;
|
||||
GET_WALLET_DATA(params?: Record<string, never>): GET_WALLET_DATA_RESPONSE;
|
||||
IONIC_SWAP(params: {
|
||||
destinationAddress: string;
|
||||
|
|
@ -138,20 +138,20 @@ export type ZanoCompanionMethods = {
|
|||
destinationAssetAmount: number | string;
|
||||
currentAssetID: string;
|
||||
currentAssetAmount: number | string;
|
||||
}): ZanoCompanionWrappedMethod<IONIC_SWAP_RESPONSE>;
|
||||
IONIC_SWAP_ACCEPT(params: { hex_raw_proposal: string }): ZanoCompanionWrappedMethod<IONIC_SWAP_ACCEPT_RESPONSE>;
|
||||
}): LetheanCompanionWrappedMethod<IONIC_SWAP_RESPONSE>;
|
||||
IONIC_SWAP_ACCEPT(params: { hex_raw_proposal: string }): LetheanCompanionWrappedMethod<IONIC_SWAP_ACCEPT_RESPONSE>;
|
||||
GET_IONIC_SWAP_PROPOSAL_INFO(params: { hex_raw_proposal: string }): GET_IONIC_SWAP_PROPOSAL_INFO_RESPONSE;
|
||||
TRANSFER(
|
||||
params: ExclusiveUnion<
|
||||
{ assetId: string; destination: string; amount: string },
|
||||
{ assetId?: string; destinations: { address: string; amount: string; assetId?: string }[] }
|
||||
> & { comment?: string },
|
||||
): ZanoCompanionWrappedMethod<TRANSFER_RESPONSE>;
|
||||
REQUEST_MESSAGE_SIGN(params: { message: string }): ZanoCompanionWrappedMethod<REQUEST_MESSAGE_SIGN_RESPONSE>;
|
||||
): LetheanCompanionWrappedMethod<TRANSFER_RESPONSE>;
|
||||
REQUEST_MESSAGE_SIGN(params: { message: string }): LetheanCompanionWrappedMethod<REQUEST_MESSAGE_SIGN_RESPONSE>;
|
||||
GET_WHITELIST(params?: Record<string, never>): GET_WHITELIST_RESPONSE;
|
||||
ASSETS_WHITELIST_ADD(params: { asset_id: string }): ZanoCompanionWrappedMethod<ASSETS_WHITELIST_ADD_RESPONSE>;
|
||||
ASSETS_WHITELIST_ADD(params: { asset_id: string }): LetheanCompanionWrappedMethod<ASSETS_WHITELIST_ADD_RESPONSE>;
|
||||
GET_ALIAS_DETAILS(params: { alias: string }): GET_ALIAS_DETAILS_RESPONSE;
|
||||
CREATE_ALIAS(params: { alias: string; comment?: string }): ZanoCompanionWrappedMethod<CREATE_ALIAS_RESPONSE>;
|
||||
CREATE_ALIAS(params: { alias: string; comment?: string }): LetheanCompanionWrappedMethod<CREATE_ALIAS_RESPONSE>;
|
||||
};
|
||||
export type ZanoCompanionMethodParams<Method extends keyof ZanoCompanionMethods> = Parameters<ZanoCompanionMethods[Method]>[0];
|
||||
export type ZanoCompanionMethodResult<Method extends keyof ZanoCompanionMethods> = ReturnType<ZanoCompanionMethods[Method]>;
|
||||
export type LetheanCompanionMethodParams<Method extends keyof LetheanCompanionMethods> = Parameters<LetheanCompanionMethods[Method]>[0];
|
||||
export type LetheanCompanionMethodResult<Method extends keyof LetheanCompanionMethods> = ReturnType<LetheanCompanionMethods[Method]>;
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
|
@ -3,5 +3,5 @@ import { defineConfig } from "vite";
|
|||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
base: "/zano-companion-testsuit/",
|
||||
base: "/lethean-companion-testsuit/",
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue