feat: implement minimum stand
This commit is contained in:
parent
84a1eda9e3
commit
b6f07adb66
@ -10,8 +10,15 @@
|
||||
|
||||
includes:
|
||||
- url: >-
|
||||
https://gitlab.com/coinweb/cweb-dapp-index/-/raw/b534ebc0dbe7faa3458f11e2bc19553ab70bc317/dapp_lock_index.yaml
|
||||
blake3: 48c6cd4b1b9252f2513efca47a0a8bd2f61417c6adc6bcd9d7e30521e735545e
|
||||
https://gitlab.com/coinweb/cweb-dapp-index/-/raw/e7180f56cbcf7c04fbdee487f271500cff637067/dapp_lock_index.yaml
|
||||
blake3: 321b1f88930aead7fe47961c8664005b3441f6502824769bf21eb06c3e5aaba4
|
||||
|
||||
use:
|
||||
- jump-listener.cm v0.1.8
|
||||
- jump_listener_devnet v0.1.8
|
||||
- jump-forwarder.cm v0.1.5
|
||||
- jump_forwarder_devnet v0.1.5
|
||||
|
||||
|
||||
|
||||
interpreters: {}
|
||||
@ -24,4 +31,6 @@ contract_templates:
|
||||
contract_instances:
|
||||
- alias: cwait-contract 0.0.1-devnet
|
||||
template: contract.cm v0.0.1
|
||||
parameters:
|
||||
content: []
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
|
||||
includes:
|
||||
- url: >-
|
||||
https://gitlab.com/coinweb/cweb-dapp-index/-/raw/35d7542b81d884adb899ea95f1433fe59b012a6c/dapp_lock_index.yaml
|
||||
blake3: 0e8f57c2c939f9cccf6912c2fb7994bb7095a1f10bef585296dba4263eb76211
|
||||
https://gitlab.com/coinweb/cweb-dapp-index/-/raw/e7180f56cbcf7c04fbdee487f271500cff637067/dapp_lock_index.yaml
|
||||
blake3: 321b1f88930aead7fe47961c8664005b3441f6502824769bf21eb06c3e5aaba4
|
||||
|
||||
interpreters: {}
|
||||
|
||||
@ -23,4 +23,5 @@ contract_templates:
|
||||
contract_instances:
|
||||
- alias: cwait-contract 0.0.1-prod
|
||||
template: contract.cm v0.0.1
|
||||
|
||||
parameters:
|
||||
content: []
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
|
||||
includes:
|
||||
- url: >-
|
||||
https://gitlab.com/coinweb/cweb-dapp-index/-/raw/5d52c2c4c39fbe74b7e86e9a9c463240df69b01d/dapp_lock_index.yaml
|
||||
blake3: a576de68122e704240acc7efe813d52cecd1519fab1078db537ed4b59da0f9ba
|
||||
https://gitlab.com/coinweb/cweb-dapp-index/-/raw/e7180f56cbcf7c04fbdee487f271500cff637067/dapp_lock_index.yaml
|
||||
blake3: 321b1f88930aead7fe47961c8664005b3441f6502824769bf21eb06c3e5aaba4
|
||||
|
||||
use:
|
||||
- dex-app.cm v0.0.67+test
|
||||
@ -29,3 +29,5 @@ contract_templates:
|
||||
contract_instances:
|
||||
- alias: cwait-contract 0.0.1-test
|
||||
template: contract.cm v0.0.1
|
||||
parameters:
|
||||
content: []
|
||||
|
||||
@ -121,6 +121,8 @@ export default tseslint.config(
|
||||
allowTypedFunctionExpressions: true,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-floating-promises': 'off',
|
||||
'@typescript-eslint/require-await': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@ -26,5 +26,8 @@
|
||||
"bech32": "2.0.0",
|
||||
"bs58": "6.0.0"
|
||||
},
|
||||
"main": "cweb_dist/offchain/index.js"
|
||||
"main": "cweb_dist/offchain/index.js",
|
||||
"engines": {
|
||||
"cweb_interpreter": "a344c6003922f9e44385f6e8234a7d2567d9a676b14330ad3b42cbd1948a92bf"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,115 +1,41 @@
|
||||
import { ClaimKey, User } from '@coinweb/contract-kit';
|
||||
import { Client } from 'cwap-cm-lib/offchain';
|
||||
import { ClaimKey } from '@coinweb/contract-kit';
|
||||
import { Client } from 'lib/offchain';
|
||||
|
||||
import {
|
||||
createActiveOrderIndexFirstPart,
|
||||
createBestByQuoteActiveIndexFirstPart,
|
||||
createBestByQuoteIndexFirstPart,
|
||||
createDateIndexFirstPart,
|
||||
createL1TxInfoFirstPart,
|
||||
createOrderStateKey,
|
||||
createOwnerlessIndexFirstPart,
|
||||
createUniquenessFirstPart,
|
||||
createUserIndexFirstPart,
|
||||
} from './shared/keys';
|
||||
import { BtcChainData, L1TxInfoData, OrderStateClaimBody } from './shared/types';
|
||||
import { OrderData } from './types';
|
||||
import { SetClaimBody, WordClaimBody } from './shared';
|
||||
import { createWordFirstPart, createSetKey, createWordKey, createByLetterFirstPart } from './shared/keys';
|
||||
|
||||
export const getActiveOrderIds = async (client: Client): Promise<string[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createActiveOrderIndexFirstPart(), null);
|
||||
|
||||
return claimsResponse.map(({ content }) => ((content.key as ClaimKey).second_part as [number, string])[1]);
|
||||
};
|
||||
|
||||
export const getBestOrderIds = async (client: Client): Promise<string[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createBestByQuoteIndexFirstPart(), null);
|
||||
|
||||
return claimsResponse.map(({ content }) => ((content.key as ClaimKey).second_part as [number, string])[1]);
|
||||
};
|
||||
|
||||
export const getBestActiveOrderIds = async (client: Client): Promise<string[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createBestByQuoteActiveIndexFirstPart(), null);
|
||||
|
||||
return claimsResponse.map(({ content }) => ((content.key as ClaimKey).second_part as [number, string])[1]);
|
||||
};
|
||||
|
||||
export const getLastOrderIds = async (client: Client): Promise<string[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createDateIndexFirstPart(), null);
|
||||
|
||||
return claimsResponse.map(({ content }) => ((content.key as ClaimKey).second_part as [number, string])[1]);
|
||||
};
|
||||
|
||||
export const getUserOrderIds = async (client: Client, user: User): Promise<string[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createUserIndexFirstPart(user), null);
|
||||
|
||||
return claimsResponse.map(({ content }) => ((content.key as ClaimKey).second_part as [number, string])[1]);
|
||||
};
|
||||
|
||||
export const getOwnerlessOrderIds = async (client: Client): Promise<string[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createOwnerlessIndexFirstPart(), null);
|
||||
|
||||
return claimsResponse.map(({ content }) => ((content.key as ClaimKey).second_part as [string])[0]);
|
||||
};
|
||||
|
||||
export const getUtxosInUse = async (client: Client): Promise<Pick<BtcChainData, 'l1TxId' | 'vout'>[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createUniquenessFirstPart(), null);
|
||||
|
||||
return claimsResponse.map(({ content: { key } }) => {
|
||||
const [l1TxId, vout] = (key as ClaimKey).second_part as [BtcChainData['l1TxId'], BtcChainData['vout']];
|
||||
|
||||
return {
|
||||
l1TxId,
|
||||
vout,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const getOrderById = async (client: Client, id: string) => {
|
||||
const key = createOrderStateKey(id);
|
||||
export const getWord = async (client: Client, id: string) => {
|
||||
const key = createWordKey(id);
|
||||
|
||||
const claimResponse = (await client.fetchClaims(key.first_part, key.second_part))[0];
|
||||
|
||||
if (!claimResponse) {
|
||||
throw new Error('Order not found');
|
||||
}
|
||||
const data = claimResponse.content.body as WordClaimBody;
|
||||
|
||||
const data = claimResponse.content.body as OrderStateClaimBody;
|
||||
|
||||
return {
|
||||
id,
|
||||
baseAmount: BigInt(data.baseAmount),
|
||||
l1Amount: BigInt(data.l1Amount),
|
||||
minL1Amount: BigInt(data.minL1Amount),
|
||||
recipient: data.recipient,
|
||||
createdAt: data.createdAt,
|
||||
activityStatus: data.activityStatus,
|
||||
paymentStatus: data.paymentStatus,
|
||||
funds: BigInt(data.funds),
|
||||
chainData: data.chainData,
|
||||
txId: data.txId,
|
||||
error: data.error,
|
||||
expirationDate: data.expirationDate,
|
||||
history: data.history,
|
||||
isOwnerless: data.isOwnerless,
|
||||
} satisfies OrderData;
|
||||
return data.word;
|
||||
};
|
||||
|
||||
export const getOwnerlessOrders = async (client: Client) => {
|
||||
const ids = await getOwnerlessOrderIds(client);
|
||||
export const getWords = async (client: Client): Promise<string[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createWordFirstPart(), null);
|
||||
|
||||
try {
|
||||
const orders = await Promise.all(ids.map((id) => getOrderById(client, id)));
|
||||
|
||||
return orders;
|
||||
} catch (e) {
|
||||
console.error({ e });
|
||||
|
||||
return [];
|
||||
}
|
||||
return claimsResponse.map(({ content }) => (content.body as WordClaimBody).word);
|
||||
};
|
||||
|
||||
export const getL1TxInfo = async (client: Client, user: User): Promise<L1TxInfoData[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createL1TxInfoFirstPart(user), null);
|
||||
export const getWordsByLetter = async (client: Client, letter: string): Promise<string[]> => {
|
||||
const indexResponse = await client.fetchClaims(createByLetterFirstPart(letter), null);
|
||||
|
||||
return claimsResponse.map((claim) => claim.content.body as L1TxInfoData);
|
||||
const ids = indexResponse.map(({ content }) => ((content.key as ClaimKey).second_part as [string])[0]);
|
||||
|
||||
const words = await Promise.all(ids.map((id) => getWord(client, id)));
|
||||
|
||||
return words;
|
||||
};
|
||||
|
||||
export const getSet = async (client: Client, letter: string): Promise<string> => {
|
||||
const key = createSetKey(letter);
|
||||
|
||||
const claimResponse = (await client.fetchClaims(key.first_part, key.second_part))[0];
|
||||
|
||||
const data = claimResponse.content.body as SetClaimBody;
|
||||
|
||||
return data.set;
|
||||
};
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
export * from './api';
|
||||
export * from './uiCommands';
|
||||
export * from './types';
|
||||
export * from './shared';
|
||||
export * from './createL1TxData';
|
||||
export * from './reexport';
|
||||
|
||||
@ -1,95 +1,13 @@
|
||||
import { BtcNetworkParams, CreateOrderBaseParams } from './types';
|
||||
|
||||
export enum Key {
|
||||
STATE = 'STATE',
|
||||
FUNDS = 'FUNDS',
|
||||
USER_INDEX = 'USER_INDEX',
|
||||
DATE_INDEX = 'DATE_INDEX',
|
||||
BEST_BY_QUOTE_INDEX = 'BEST_BY_QUOTE_INDEX',
|
||||
ACTIVE_INDEX = 'ACTIVE_INDEX',
|
||||
OWNERLESS_INDEX = 'OWNERLESS_INDEX',
|
||||
CLOSED_INDEX = 'CLOSED_INDEX',
|
||||
ERROR_INDEX = 'ERROR_INDEX',
|
||||
UNIQUENESS_CHECK = 'UNIQUENESS_CHECK',
|
||||
CONTRACT_OWNER = 'CONTRACT_OWNER',
|
||||
L1_TX_INFO = 'L1_TX_INFO',
|
||||
INCREMENT_INDEX = 'INCREMENT_INDEX',
|
||||
}
|
||||
|
||||
export enum ACTIVITY_STATUS {
|
||||
ACTIVE = 'ACTIVE',
|
||||
COMPLETED = 'COMPLETED',
|
||||
CANCELLING = 'CANCELLING',
|
||||
CANCELLED = 'CANCELLED',
|
||||
EXPIRED = 'EXPIRED',
|
||||
ERROR = 'ERROR',
|
||||
}
|
||||
|
||||
export enum PAYMENT_STATUS {
|
||||
PAYABLE = 'PAYABLE',
|
||||
NOT_PAYABLE = 'NOT_PAYABLE',
|
||||
PAID = 'PAID',
|
||||
WORD = 'WORD',
|
||||
SET = 'SET',
|
||||
BY_LETTER = 'BY_LETTER',
|
||||
}
|
||||
|
||||
export enum PUBLIC_METHODS {
|
||||
CREATE_ORDER = '0x01',
|
||||
CANCEL_ORDER = '0x02',
|
||||
CHANGE_CONTRACT_OWNER = '0x03',
|
||||
ADD_WORD = 'ADD_WORD',
|
||||
}
|
||||
|
||||
export const FEE = {
|
||||
CREATE_ORDER: 2000000n,
|
||||
CANCEL_ORDER: 1000000n,
|
||||
ADD_WORD: 10000n,
|
||||
};
|
||||
|
||||
export enum CallType {
|
||||
Accept = 128,
|
||||
TransferWithSelfTokenFallback = 129,
|
||||
TransferWithQuoteTokenFallback = 130,
|
||||
}
|
||||
|
||||
export enum Encoding {
|
||||
Hex = 128,
|
||||
Base58 = 129,
|
||||
Bech32 = 130,
|
||||
Bech32m = 131,
|
||||
}
|
||||
|
||||
export enum L1Network {}
|
||||
|
||||
export const BTC_MAIN_NET = {
|
||||
bech32: 'bc',
|
||||
pubKeyHash: 0x00,
|
||||
scriptHash: 0x05,
|
||||
wif: 0x80,
|
||||
};
|
||||
|
||||
export const BTC_TEST_NET: BtcNetworkParams = {
|
||||
bech32: 'tb',
|
||||
pubKeyHash: 0x6f,
|
||||
scriptHash: 0xc4,
|
||||
wif: 0xef,
|
||||
};
|
||||
|
||||
export const BtcShardNetwork = {
|
||||
btc: BTC_MAIN_NET,
|
||||
tbtc: BTC_TEST_NET,
|
||||
} satisfies Record<'btc' | 'tbtc', BtcNetworkParams>;
|
||||
|
||||
export enum BtcNetworkCode {
|
||||
btc = 128,
|
||||
tbtc = 129,
|
||||
}
|
||||
|
||||
export const BtcCodeNetwork = {
|
||||
[BtcNetworkCode.btc]: BTC_MAIN_NET,
|
||||
[BtcNetworkCode.tbtc]: BTC_TEST_NET,
|
||||
};
|
||||
|
||||
export const OrderBatchFields = [
|
||||
'l1Amount',
|
||||
'l1Address',
|
||||
'minL1Amount',
|
||||
'baseAmount',
|
||||
'chainData',
|
||||
] as const satisfies (keyof CreateOrderBaseParams)[];
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
export * from './keys';
|
||||
export * from './utils';
|
||||
export * from './constants';
|
||||
export * from './types';
|
||||
export { parseL1TxData } from '../createL1TxData';
|
||||
|
||||
@ -1,115 +1,29 @@
|
||||
import type { ClaimKey, OrdJson, User } from '@coinweb/contract-kit';
|
||||
import type { ClaimKey } from '@coinweb/contract-kit';
|
||||
|
||||
import { Key } from './constants';
|
||||
import { BtcChainData } from './types';
|
||||
|
||||
/* FirstPart */
|
||||
export const createWordFirstPart = () => [Key.WORD];
|
||||
|
||||
export const createOrderStateFirstPart = () => [Key.STATE];
|
||||
export const createByLetterFirstPart = (letter: string) => [Key.BY_LETTER, letter];
|
||||
|
||||
export const createOrderFundsFirstPart = () => [Key.FUNDS];
|
||||
|
||||
export const createDateIndexFirstPart = () => [Key.DATE_INDEX];
|
||||
|
||||
export const createBestByQuoteIndexFirstPart = () => [Key.BEST_BY_QUOTE_INDEX];
|
||||
|
||||
export const createActiveOrderIndexFirstPart = () => [Key.ACTIVE_INDEX];
|
||||
|
||||
export const createBestByQuoteActiveIndexFirstPart = () => [Key.BEST_BY_QUOTE_INDEX, Key.ACTIVE_INDEX];
|
||||
|
||||
export const createUserIndexFirstPart = (user: User) => [Key.USER_INDEX, user];
|
||||
|
||||
export const createClosedIndexFirstPart = () => [Key.CLOSED_INDEX];
|
||||
|
||||
export const createOwnerlessIndexFirstPart = () => [Key.OWNERLESS_INDEX];
|
||||
|
||||
export const createOwnerFirstPart = () => [Key.CONTRACT_OWNER];
|
||||
|
||||
export const createUniquenessFirstPart = () => [Key.UNIQUENESS_CHECK]; //TODO: Add second element as a type of uniqueness
|
||||
|
||||
export const createL1TxInfoFirstPart = (user: User | null) => [Key.L1_TX_INFO, user];
|
||||
export const createSetFirstPart = () => [Key.SET];
|
||||
|
||||
/* Key */
|
||||
export const createOrderStateKey = (orderId: string) =>
|
||||
export const createWordKey = (id: string) =>
|
||||
({
|
||||
first_part: createOrderStateFirstPart(),
|
||||
second_part: [orderId],
|
||||
first_part: createWordFirstPart(),
|
||||
second_part: [id],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createOrderFundsKey = (orderId: string) =>
|
||||
export const createByLetterKey = (letter: string, id: string) =>
|
||||
({
|
||||
first_part: createOrderFundsFirstPart(),
|
||||
second_part: [orderId],
|
||||
first_part: createByLetterFirstPart(letter),
|
||||
second_part: [id],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createDateIndexKey = (timestamp: number, orderId: string) =>
|
||||
export const createSetKey = (letter: string) =>
|
||||
({
|
||||
first_part: createDateIndexFirstPart(),
|
||||
second_part: [Number.MAX_SAFE_INTEGER - timestamp, orderId],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createBestByQuoteIndexKey = (rate: bigint, orderId: string) =>
|
||||
({
|
||||
first_part: createBestByQuoteIndexFirstPart(),
|
||||
second_part: [rate.toString(16), orderId],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createActiveOrderIndexKey = (timestamp: number, orderId: string) =>
|
||||
({
|
||||
first_part: createActiveOrderIndexFirstPart(),
|
||||
second_part: [Number.MAX_SAFE_INTEGER - timestamp, orderId],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createBestByQuoteActiveIndexKey = (rate: bigint, orderId: string) =>
|
||||
({
|
||||
first_part: createBestByQuoteActiveIndexFirstPart(),
|
||||
second_part: [rate.toString(16), orderId],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createUserIndexKey = (user: User, timestamp: number, orderId: string) =>
|
||||
({
|
||||
first_part: createUserIndexFirstPart(user),
|
||||
second_part: [Number.MAX_SAFE_INTEGER - timestamp, orderId],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createClosedIndexKey = (orderId: string) =>
|
||||
({
|
||||
first_part: createClosedIndexFirstPart(),
|
||||
second_part: [orderId],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createOwnerlessIndexKey = (orderId: string) =>
|
||||
({
|
||||
first_part: createOwnerlessIndexFirstPart(),
|
||||
second_part: [orderId],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createOwnerKey = () =>
|
||||
({
|
||||
first_part: createOwnerFirstPart(),
|
||||
second_part: [],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createUniquenessKey = (data: OrdJson) =>
|
||||
({
|
||||
first_part: createUniquenessFirstPart(),
|
||||
second_part: data,
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createBtcUtxoUniquenessKey = (data: BtcChainData) =>
|
||||
({
|
||||
first_part: createUniquenessFirstPart(),
|
||||
second_part: [data.l1TxId, data.vout],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createL1TxKey = (timestamp: number, uniqueId: string, user: User | null) =>
|
||||
({
|
||||
first_part: createL1TxInfoFirstPart(user),
|
||||
second_part: [Number.MAX_SAFE_INTEGER - timestamp, uniqueId],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createIdIncrementIndexKey = () =>
|
||||
({
|
||||
first_part: [Key.INCREMENT_INDEX],
|
||||
second_part: [Key.INCREMENT_INDEX],
|
||||
first_part: createSetFirstPart(),
|
||||
second_part: [letter],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
@ -1,124 +1,9 @@
|
||||
import type { HexString, User } from '@coinweb/contract-kit';
|
||||
import { HistoryAccess } from 'cwap-cm-lib/history/shared';
|
||||
import { HexBigInt, BigIntToHex, L1Types } from 'cwap-cm-lib/shared';
|
||||
|
||||
import { ACTIVITY_STATUS, PAYMENT_STATUS, CallType, BTC_MAIN_NET, OrderBatchFields } from './constants';
|
||||
|
||||
export type PubKey = string;
|
||||
|
||||
export type OrderStateClaimBody = {
|
||||
recipient: string;
|
||||
baseAmount: HexBigInt;
|
||||
l1Amount: HexBigInt;
|
||||
minL1Amount: HexBigInt;
|
||||
createdAt: number;
|
||||
expirationDate: number;
|
||||
activityStatus: ACTIVITY_STATUS;
|
||||
paymentStatus: PAYMENT_STATUS;
|
||||
funds: HexBigInt;
|
||||
chainData: ChainData;
|
||||
txId: string;
|
||||
error: string | null;
|
||||
isOwnerless?: boolean;
|
||||
history: HistoryAccess;
|
||||
export type SetClaimBody = {
|
||||
set: string;
|
||||
};
|
||||
|
||||
export type OrderFundsClaimBody = {
|
||||
owner: User;
|
||||
export type WordClaimBody = {
|
||||
word: string;
|
||||
};
|
||||
|
||||
export type ChainData = unknown;
|
||||
|
||||
export type BtcChainData = {
|
||||
l1TxId: string;
|
||||
vout: number;
|
||||
psbt: string;
|
||||
};
|
||||
|
||||
export type L1TxInfoData = {
|
||||
l1TxId: string;
|
||||
recipientAddress: string;
|
||||
backPayAddress: string;
|
||||
amount: HexBigInt;
|
||||
l2TxId: string;
|
||||
};
|
||||
|
||||
type L1TxAcceptPayload = {
|
||||
baseRecipient: HexString;
|
||||
};
|
||||
|
||||
type L1TxTransferBasePayload = {
|
||||
c2ContractId: HexString;
|
||||
c2ContractMethod: HexString;
|
||||
minL1Amount: HexBigInt;
|
||||
promisedL1Amount: HexBigInt;
|
||||
l1Recipient: HexString;
|
||||
l1ChainType: L1Types;
|
||||
};
|
||||
|
||||
type L1TxTransferWithSelfFallbackPayload = {
|
||||
fallbackRecipient: string;
|
||||
} & L1TxTransferBasePayload;
|
||||
|
||||
type L1TxTransferWithQuoteFallbackPayload = {
|
||||
fallbackC1ContractId: HexString;
|
||||
fallbackC1ContractMethod: HexString;
|
||||
} & L1TxTransferBasePayload;
|
||||
|
||||
export type AcceptData = {
|
||||
callType: CallType.Accept;
|
||||
} & L1TxAcceptPayload;
|
||||
|
||||
export type TransferWithSelfFallbackData = {
|
||||
callType: CallType.TransferWithSelfTokenFallback;
|
||||
} & L1TxTransferWithSelfFallbackPayload;
|
||||
|
||||
export type TransferWithQuoteFallbackData = {
|
||||
callType: CallType.TransferWithQuoteTokenFallback;
|
||||
} & L1TxTransferWithQuoteFallbackPayload;
|
||||
|
||||
export type CreateOrderBaseParams = {
|
||||
l1Amount: bigint;
|
||||
l1Address: string;
|
||||
minL1Amount?: bigint;
|
||||
baseAmount?: bigint;
|
||||
chainData?: ChainData;
|
||||
};
|
||||
|
||||
export type CreateOrderEvmBaseParams = CreateOrderBaseParams;
|
||||
export type CreateOrderBtcBaseParams = Omit<CreateOrderBaseParams, 'chainData'> & {
|
||||
chainData: BtcChainData;
|
||||
};
|
||||
|
||||
export type OrdersBatch<T extends CreateOrderBaseParams = CreateOrderBaseParams> = [
|
||||
number,
|
||||
Partial<T>,
|
||||
Partial<T>[]?,
|
||||
][];
|
||||
export type EvmOrdersBatch = OrdersBatch<CreateOrderEvmBaseParams>;
|
||||
export type BtcOrdersBatch = OrdersBatch<CreateOrderBtcBaseParams>;
|
||||
|
||||
export type SerializableOrderParams = BigIntToHex<CreateOrderBaseParams>;
|
||||
|
||||
type BatchFields = typeof OrderBatchFields;
|
||||
|
||||
export type SerializedOrderTemplate = {
|
||||
[I in keyof BatchFields & `${number}`]: BatchFields[I] extends keyof CreateOrderBaseParams
|
||||
? BigIntToHex<Required<CreateOrderBaseParams[BatchFields[I]]>> | null
|
||||
: never;
|
||||
};
|
||||
|
||||
export type SerializedOrderTune = {
|
||||
[I in keyof BatchFields & `${number}`]?: BatchFields[I] extends keyof CreateOrderBaseParams
|
||||
? BigIntToHex<CreateOrderBaseParams[BatchFields[I]]>
|
||||
: never;
|
||||
};
|
||||
|
||||
export type SerializedOrdersBatch = [OrdersBatch[number][0], SerializedOrderTemplate, SerializedOrderTune[]?][];
|
||||
|
||||
export type CreateOrderCallArgs = [orders: SerializedOrdersBatch];
|
||||
|
||||
export type CancelOrderArguments = [ids: string[]];
|
||||
export type ChangeContractOwnerArguments = [newOwner: User];
|
||||
|
||||
export type BtcNetworkParams = typeof BTC_MAIN_NET;
|
||||
export type AddWordArgs = [string];
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
import { HexBigInt, BigIntToHex, toHex32, toHex } from 'cwap-cm-lib/shared';
|
||||
|
||||
import { FEE, OrderBatchFields } from './constants';
|
||||
import { OrdersBatch, SerializedOrdersBatch, CreateOrderBaseParams, SerializedOrderTemplate } from './types';
|
||||
|
||||
export const ordersBatchToList = (ordersBatch: OrdersBatch) => {
|
||||
return ordersBatch
|
||||
.map((orderSet) => {
|
||||
const orders = Array(orderSet[0])
|
||||
.fill(orderSet[1])
|
||||
.map((order, i) => ({ ...order, ...orderSet[2]?.[i] }) as CreateOrderBaseParams);
|
||||
|
||||
return orders;
|
||||
}, [])
|
||||
.flat();
|
||||
};
|
||||
|
||||
export const serializeOrdersBatch = (ordersBatch: OrdersBatch): SerializedOrdersBatch => {
|
||||
return ordersBatch.map(([count, base, tunes]) => [
|
||||
count,
|
||||
[
|
||||
base.l1Amount ? toHex32(base.l1Amount) : null,
|
||||
base.l1Address ? base.l1Address : null,
|
||||
base.minL1Amount ? toHex32(base.minL1Amount) : null,
|
||||
base.baseAmount ? toHex32(base.baseAmount) : null,
|
||||
base.chainData ? base.chainData : null,
|
||||
],
|
||||
tunes?.map((tune) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(tune).map(([key, value]) => [
|
||||
OrderBatchFields.findIndex((field) => field === key),
|
||||
['baseAmount', 'l1Amount', 'minL1Amount'].includes(key) ? toHex(value as bigint) : value,
|
||||
])
|
||||
)
|
||||
),
|
||||
]);
|
||||
};
|
||||
|
||||
export const deserializeBatchToList = (ordersBatch: SerializedOrdersBatch): CreateOrderBaseParams[] => {
|
||||
return ordersBatch
|
||||
.map((orderSet) => {
|
||||
const orders = Array(orderSet[0])
|
||||
.fill(
|
||||
Object.fromEntries(
|
||||
OrderBatchFields.map((field, i) => [
|
||||
field,
|
||||
orderSet[1][i as unknown as keyof SerializedOrderTemplate],
|
||||
]).filter(([_, value]) => value !== null)
|
||||
)
|
||||
)
|
||||
.map((order: Partial<BigIntToHex<CreateOrderBaseParams>>, i) => ({
|
||||
...order,
|
||||
...(orderSet[2]?.[i] &&
|
||||
Object.fromEntries(
|
||||
Object.entries(orderSet[2][i]).map(([key, value]) => [OrderBatchFields[Number(key)], value])
|
||||
)),
|
||||
}))
|
||||
.map((order) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(order).map(([key, value]) => {
|
||||
return [
|
||||
key,
|
||||
['baseAmount', 'l1Amount', 'minL1Amount'].includes(key) && value ? BigInt(value as HexBigInt) : value,
|
||||
];
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
return orders;
|
||||
}, [])
|
||||
.flat() as CreateOrderBaseParams[];
|
||||
};
|
||||
|
||||
export const calculateOrdersListParams = (orders: CreateOrderBaseParams[]) => {
|
||||
const ordersLength = BigInt(orders.length);
|
||||
const { l1Amount, minL1Amount, definedBaseAmount, itemsWithUndefinedBaseAmount } = orders.reduce(
|
||||
(result, order) => {
|
||||
if (!order.l1Amount) {
|
||||
throw new Error('creteNewOrderUiCommand: wrong arguments received');
|
||||
}
|
||||
|
||||
return {
|
||||
l1Amount: result.l1Amount + BigInt(order.l1Amount),
|
||||
minL1Amount: result.minL1Amount + BigInt(order.minL1Amount ?? 0),
|
||||
definedBaseAmount: result.definedBaseAmount + BigInt(order.baseAmount ?? 0),
|
||||
itemsWithUndefinedBaseAmount: result.itemsWithUndefinedBaseAmount + (order.baseAmount ? 0n : 1n),
|
||||
};
|
||||
},
|
||||
{ l1Amount: 0n, minL1Amount: 0n, definedBaseAmount: 0n, itemsWithUndefinedBaseAmount: 0n }
|
||||
);
|
||||
|
||||
return {
|
||||
l1Amount,
|
||||
minL1Amount,
|
||||
definedBaseAmount,
|
||||
itemsWithUndefinedBaseAmount,
|
||||
fee: FEE.CREATE_ORDER * ordersLength,
|
||||
isBatch: ordersLength > 1n,
|
||||
ordersLength,
|
||||
};
|
||||
};
|
||||
@ -1,52 +0,0 @@
|
||||
import {
|
||||
BtcOrdersBatch,
|
||||
ChainData,
|
||||
CreateOrderBaseParams,
|
||||
CreateOrderBtcBaseParams,
|
||||
CreateOrderEvmBaseParams,
|
||||
EvmOrdersBatch,
|
||||
OrdersBatch,
|
||||
OrderStateClaimBody,
|
||||
} from './shared';
|
||||
|
||||
export type CreateOrderData<T extends CreateOrderBaseParams = CreateOrderBaseParams> = T & {
|
||||
contractId: string;
|
||||
contractOwnerFee: bigint;
|
||||
accessId?: string;
|
||||
};
|
||||
|
||||
export type CreateOrderBtcData = CreateOrderData<CreateOrderBtcBaseParams>;
|
||||
export type CreateOrderEvmData = CreateOrderData<CreateOrderEvmBaseParams>;
|
||||
|
||||
export type CreateOrdersData<T extends OrdersBatch = OrdersBatch> = {
|
||||
contractId: string;
|
||||
orders: T;
|
||||
contractOwnerFee: bigint;
|
||||
accessId?: string;
|
||||
};
|
||||
|
||||
export type CreateOrdersBtcData = CreateOrdersData<BtcOrdersBatch>;
|
||||
export type CreateOrdersEvmData = CreateOrdersData<EvmOrdersBatch>;
|
||||
|
||||
export type CancelOrderData = {
|
||||
contractId: string;
|
||||
orderId: string;
|
||||
accessId?: string;
|
||||
};
|
||||
|
||||
export type CancelOrdersData = {
|
||||
contractId: string;
|
||||
orderIds: string[];
|
||||
accessId?: string;
|
||||
};
|
||||
|
||||
type OrderDataTransformed = {
|
||||
id: string;
|
||||
baseAmount: bigint;
|
||||
l1Amount: bigint;
|
||||
minL1Amount: bigint;
|
||||
funds: bigint;
|
||||
chainData?: ChainData;
|
||||
};
|
||||
|
||||
export type OrderData = OrderDataTransformed & Omit<OrderStateClaimBody, keyof OrderDataTransformed>;
|
||||
@ -1,130 +1,14 @@
|
||||
import { withMetadata } from 'cwap-cm-lib/history/offchain';
|
||||
import { HISTORY_ACCESS_FEE } from 'cwap-cm-lib/history/shared';
|
||||
import { constructCall, constructUiCommand } from 'cwap-cm-lib/offchain';
|
||||
import { constructCall, constructUiCommand } from 'lib/offchain';
|
||||
|
||||
import { FEE, serializeOrdersBatch, PUBLIC_METHODS, ordersBatchToList, calculateOrdersListParams } from './shared';
|
||||
import {
|
||||
CancelOrdersData,
|
||||
CreateOrdersBtcData,
|
||||
CreateOrdersEvmData,
|
||||
CreateOrdersData,
|
||||
CancelOrderData,
|
||||
CreateOrderBtcData,
|
||||
CreateOrderEvmData,
|
||||
} from './types';
|
||||
|
||||
const constructCreateOrdersCall = ({ contractId, accessId, orders, contractOwnerFee }: CreateOrdersData) => {
|
||||
const { l1Amount, minL1Amount, definedBaseAmount, fee } = calculateOrdersListParams(ordersBatchToList(orders));
|
||||
|
||||
if (l1Amount < minL1Amount) {
|
||||
throw new Error('creteNewOrderUiCommand: l1Amount is less than minimum value');
|
||||
}
|
||||
|
||||
return constructCall(
|
||||
contractId,
|
||||
PUBLIC_METHODS.CREATE_ORDER,
|
||||
withMetadata([serializeOrdersBatch(orders)], accessId),
|
||||
definedBaseAmount + fee + contractOwnerFee + (accessId ? HISTORY_ACCESS_FEE : 0n)
|
||||
);
|
||||
};
|
||||
|
||||
export const constructCreateBtcOrdersCall = (data: CreateOrdersBtcData) => {
|
||||
return constructCreateOrdersCall(data);
|
||||
};
|
||||
|
||||
export const constructCreateEvmOrdersCall = (data: CreateOrdersEvmData) => {
|
||||
return constructCreateOrdersCall(data);
|
||||
};
|
||||
|
||||
export const constructCancelOrdersCall = ({ contractId, orderIds, accessId }: CancelOrdersData) => {
|
||||
return constructCall(
|
||||
contractId,
|
||||
PUBLIC_METHODS.CANCEL_ORDER,
|
||||
withMetadata([orderIds], accessId),
|
||||
FEE.CANCEL_ORDER * BigInt(orderIds.length) + (accessId ? HISTORY_ACCESS_FEE : 0n)
|
||||
);
|
||||
};
|
||||
|
||||
export const createOrderBtcUiCommand = ({
|
||||
contractId,
|
||||
baseAmount,
|
||||
l1Amount,
|
||||
minL1Amount,
|
||||
l1Address,
|
||||
chainData,
|
||||
accessId,
|
||||
contractOwnerFee,
|
||||
}: CreateOrderBtcData) => {
|
||||
if (!baseAmount) {
|
||||
throw new Error('createOrderBtcUiCommand: baseAmount is not defined');
|
||||
}
|
||||
import { AddWordArgs, FEE, PUBLIC_METHODS } from './shared';
|
||||
|
||||
export const constructAddWordUiCommand = ({ word, contractId }: { word: string; contractId: string }) => {
|
||||
return constructUiCommand([
|
||||
constructCreateOrdersCall({
|
||||
constructCall({
|
||||
contractId,
|
||||
orders: [
|
||||
[
|
||||
1,
|
||||
{
|
||||
baseAmount,
|
||||
l1Amount,
|
||||
minL1Amount,
|
||||
l1Address,
|
||||
chainData,
|
||||
},
|
||||
],
|
||||
],
|
||||
accessId,
|
||||
contractOwnerFee,
|
||||
methodName: PUBLIC_METHODS.ADD_WORD,
|
||||
methodArgs: [[word] satisfies AddWordArgs],
|
||||
cost: FEE.ADD_WORD,
|
||||
}),
|
||||
]);
|
||||
};
|
||||
|
||||
export const createOrderEvmUiCommand = ({
|
||||
contractId,
|
||||
baseAmount,
|
||||
l1Amount,
|
||||
minL1Amount,
|
||||
l1Address,
|
||||
accessId,
|
||||
contractOwnerFee,
|
||||
}: CreateOrderEvmData) => {
|
||||
if (!baseAmount) {
|
||||
throw new Error('createOrderEvmUiCommand: baseAmount is not defined');
|
||||
}
|
||||
|
||||
return constructUiCommand([
|
||||
constructCreateOrdersCall({
|
||||
contractId,
|
||||
orders: [
|
||||
[
|
||||
1,
|
||||
{
|
||||
baseAmount,
|
||||
l1Amount,
|
||||
minL1Amount,
|
||||
l1Address,
|
||||
},
|
||||
],
|
||||
],
|
||||
accessId,
|
||||
contractOwnerFee,
|
||||
}),
|
||||
]);
|
||||
};
|
||||
|
||||
export const createOrdersBtcUiCommand = (data: CreateOrdersBtcData) => {
|
||||
return constructUiCommand([constructCreateOrdersCall(data)]);
|
||||
};
|
||||
|
||||
export const createOrdersEvmUiCommand = (data: CreateOrdersEvmData) => {
|
||||
return constructUiCommand([constructCreateOrdersCall(data)]);
|
||||
};
|
||||
|
||||
export const cancelOrderUiCommand = ({ contractId, orderId, accessId }: CancelOrderData) => {
|
||||
return constructUiCommand([constructCancelOrdersCall({ contractId, orderIds: [orderId], accessId })]);
|
||||
};
|
||||
|
||||
export const cancelOrdersUiCommand = (data: CancelOrdersData) => {
|
||||
return constructUiCommand([constructCancelOrdersCall(data)]);
|
||||
};
|
||||
|
||||
21
packages/contract.cm/src/onchain/addWord.ts
Normal file
21
packages/contract.cm/src/onchain/addWord.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { constructClaim } from '@coinweb/contract-kit';
|
||||
import { storeOp } from 'cwait';
|
||||
|
||||
import { AddWordArgs, createWordKey } from '../offchain/shared';
|
||||
|
||||
function hashCode(str: string): string {
|
||||
let hash = 0;
|
||||
for (let i = 0, len = str.length; i < len; i++) {
|
||||
const chr = str.charCodeAt(i);
|
||||
// eslint-disable-next-line no-bitwise
|
||||
hash = (hash << 5) - hash + chr;
|
||||
// eslint-disable-next-line no-bitwise
|
||||
hash |= 0;
|
||||
}
|
||||
return `${hash.toString(16)}`;
|
||||
}
|
||||
|
||||
export const addWord = async (...[word]: AddWordArgs) => {
|
||||
const id = hashCode(word);
|
||||
storeOp(constructClaim(createWordKey(id), { word }, '0x0'));
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
export const PRIVATE_METHODS = {
|
||||
CREATE_ORDER: 'CREATE_ORDER_PRIVATE',
|
||||
CREATE_ORDER_INDEXES: 'CREATE_ORDER_INDEXES_PRIVATE',
|
||||
DEACTIVATE_ORDER: 'DEACTIVATE_ORDER_PRIVATE',
|
||||
CLOSE_ORDER: 'CLOSE_ORDER_PRIVATE',
|
||||
HANDLE_BLOCK_TRIGGERED: 'HANDLE_BLOCK_TRIGGERED_PRIVATE',
|
||||
CHANGE_CONTRACT_OWNER: 'CHANGE_CONTRACT_OWNER_PRIVATE',
|
||||
};
|
||||
@ -1,56 +1,30 @@
|
||||
import {
|
||||
ContractHandlers,
|
||||
MethodCallback,
|
||||
SELF_REGISTER_HANDLER_NAME,
|
||||
addMethodHandler,
|
||||
executeHandler,
|
||||
selfCallWrapper,
|
||||
} from '@coinweb/contract-kit';
|
||||
import { SELF_REGISTER_HANDLER_NAME, ContractHandlers as CKContractHandlers } from '@coinweb/contract-kit';
|
||||
import { selfRegisterHandler } from '@coinweb/self-register';
|
||||
import { queue, withContractCallLogger } from 'cwap-cm-lib/onchain';
|
||||
import { addMethodHandler, ContractHandlers, executeHandler, executor, MethodCallback, selfCallWrapper } from 'cwait';
|
||||
import { queue } from 'lib/onchain';
|
||||
|
||||
import { PUBLIC_METHODS } from '../offchain/shared';
|
||||
|
||||
import { PRIVATE_METHODS } from './constants';
|
||||
import {
|
||||
cancelOrderPublic,
|
||||
changeContractOwner,
|
||||
changeOwnerPublic,
|
||||
closeOrder,
|
||||
createOrderIndexes,
|
||||
createOrder,
|
||||
createOrderPublic,
|
||||
deactivateOrder,
|
||||
handleBlockTriggered,
|
||||
} from './methods';
|
||||
import { addWord } from './addWord';
|
||||
|
||||
const addWrappers = (method: MethodCallback): MethodCallback => {
|
||||
return selfCallWrapper(withContractCallLogger(method));
|
||||
return selfCallWrapper(method);
|
||||
};
|
||||
|
||||
export const cwebMain = () => {
|
||||
const createModule = (): ContractHandlers => {
|
||||
const module: ContractHandlers = { handlers: {} };
|
||||
|
||||
addMethodHandler(module, PUBLIC_METHODS.CREATE_ORDER, addWrappers(createOrderPublic));
|
||||
addMethodHandler(module, PRIVATE_METHODS.CREATE_ORDER, addWrappers(createOrder));
|
||||
addMethodHandler(module, PRIVATE_METHODS.CREATE_ORDER_INDEXES, addWrappers(createOrderIndexes));
|
||||
|
||||
addMethodHandler(module, PRIVATE_METHODS.HANDLE_BLOCK_TRIGGERED, addWrappers(handleBlockTriggered));
|
||||
|
||||
addMethodHandler(module, PUBLIC_METHODS.CANCEL_ORDER, addWrappers(cancelOrderPublic));
|
||||
addMethodHandler(module, PRIVATE_METHODS.DEACTIVATE_ORDER, addWrappers(deactivateOrder));
|
||||
addMethodHandler(module, PRIVATE_METHODS.CLOSE_ORDER, addWrappers(closeOrder));
|
||||
|
||||
addMethodHandler(module, PUBLIC_METHODS.CHANGE_CONTRACT_OWNER, addWrappers(changeOwnerPublic));
|
||||
addMethodHandler(module, PRIVATE_METHODS.CHANGE_CONTRACT_OWNER, addWrappers(changeContractOwner));
|
||||
addMethodHandler(module, PUBLIC_METHODS.ADD_WORD, addWrappers(executor(addWord)));
|
||||
|
||||
addMethodHandler(module, SELF_REGISTER_HANDLER_NAME, selfRegisterHandler);
|
||||
|
||||
queue.applyQueue(module, [
|
||||
PUBLIC_METHODS.CANCEL_ORDER,
|
||||
PUBLIC_METHODS.CHANGE_CONTRACT_OWNER,
|
||||
PUBLIC_METHODS.CREATE_ORDER,
|
||||
]);
|
||||
queue.applyQueue(module as CKContractHandlers, [PUBLIC_METHODS.ADD_WORD]);
|
||||
|
||||
executeHandler(module);
|
||||
return module;
|
||||
};
|
||||
|
||||
export const cwebMain = async () => {
|
||||
const module = createModule();
|
||||
|
||||
await executeHandler(module);
|
||||
};
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
import { HexString, Shard, User } from '@coinweb/contract-kit';
|
||||
import { Logs } from 'cwap-cm-lib/onchain';
|
||||
import { HexBigInt, L1Types } from 'cwap-cm-lib/shared';
|
||||
|
||||
import { AcceptData, TransferWithSelfFallbackData, TransferWithQuoteFallbackData } from '../offchain/shared';
|
||||
|
||||
export type EvmEventClaimBody = {
|
||||
data: string;
|
||||
l1_txid: string;
|
||||
};
|
||||
|
||||
export type BtcEventClaimBody = {
|
||||
UtxoBased: {
|
||||
vout: {
|
||||
scriptPubKey: {
|
||||
asm: string;
|
||||
};
|
||||
}[];
|
||||
txid: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type CallContractData = {
|
||||
c2Contract: string;
|
||||
c2MethodName: string;
|
||||
c2Args: [...args: unknown[]];
|
||||
};
|
||||
|
||||
export type L1EventData = {
|
||||
recipient: HexBigInt;
|
||||
paidAmount: HexBigInt;
|
||||
l1TxId: string;
|
||||
} & (AcceptData | TransferWithSelfFallbackData | TransferWithQuoteFallbackData);
|
||||
|
||||
export type InstanceParameters = {
|
||||
l1_type: L1Types;
|
||||
l1_contract_address?: string;
|
||||
l1_transfer_event_signature?: string;
|
||||
shard: Shard;
|
||||
owner: User;
|
||||
logs?: Logs[];
|
||||
owner_min_fee?: HexString;
|
||||
owner_percentage_fee?: number;
|
||||
order_life_time: number;
|
||||
close_order_timeout: number;
|
||||
jump_contract_id: string;
|
||||
jump_contract_method: string;
|
||||
jump_contract_jumps: number;
|
||||
};
|
||||
|
||||
export type InstanceParametersForEvm = {
|
||||
l1_type: L1Types.Evm;
|
||||
l1_contract_address: string;
|
||||
l1_transfer_event_signature: string;
|
||||
} & Omit<InstanceParameters, 'l1_type' | 'l1_contract_address' | 'l1_transfer_event_signature'>;
|
||||
|
||||
export type InstanceParametersForBtc = {
|
||||
l1_type: L1Types.Btc;
|
||||
} & Omit<InstanceParameters, 'l1_type' | 'l1_contract_address' | 'l1_transfer_event_signature'>;
|
||||
|
||||
export type OwnerClaimBody = {
|
||||
owner: User;
|
||||
updatedAt: number;
|
||||
};
|
||||
@ -18,8 +18,8 @@
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/onchain/index.d.ts",
|
||||
"import": "./dist/onchain/index.js"
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
packages/cwait/src/contract-kit/index.ts
Normal file
3
packages/cwait/src/contract-kit/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './types';
|
||||
export * from './methods';
|
||||
export * from './wrappers';
|
||||
59
packages/cwait/src/contract-kit/methods.ts
Normal file
59
packages/cwait/src/contract-kit/methods.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { extractContinuations, Context } from '@coinweb/contract-kit';
|
||||
import {
|
||||
getContextCall,
|
||||
getContextGenesis,
|
||||
getContextSystem,
|
||||
getContextTx,
|
||||
writeToResultFile,
|
||||
} from '@coinweb/contract-kit/dist/esm/context';
|
||||
import { getMethodName } from '@coinweb/contract-kit/dist/esm/method';
|
||||
|
||||
import { ContractHandlers, MethodCallback } from './types';
|
||||
|
||||
/**
|
||||
* Adds a method handler for a specific method name.
|
||||
* @param contract_module - Contract module containing the method.
|
||||
* @param methodName - The name of the method.
|
||||
* @param handler - The method callback to add.
|
||||
*/
|
||||
export function addMethodHandler(contract_module: ContractHandlers, methodName: string, handler: MethodCallback): void {
|
||||
contract_module.handlers[methodName] = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the method handler for a specific method name.
|
||||
* @param contract_module - Contract module containing the method.
|
||||
* @param methodName - The name of the method.
|
||||
* @returns The method callback for the specified method name.
|
||||
* @throws Will throw an error if no handler is specified for the method name.
|
||||
*/
|
||||
export function getMethodHandler(contract_module: ContractHandlers, methodName: string): MethodCallback {
|
||||
const handler = contract_module.handlers[methodName];
|
||||
if (!handler) {
|
||||
throw Error('Handler not specified for this method name');
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the handler for the method specified in the transaction context.
|
||||
* The results (new transactions) are written to the result file.
|
||||
* @param contractModule - Contract module containing the method.
|
||||
*/
|
||||
export async function executeHandler(contractModule: ContractHandlers): Promise<void> {
|
||||
const contextTx = getContextTx();
|
||||
const contextCall = getContextCall();
|
||||
const genesis = getContextGenesis();
|
||||
const system = getContextSystem();
|
||||
const context: Context = {
|
||||
tx: contextTx,
|
||||
call: contextCall,
|
||||
genesis,
|
||||
system,
|
||||
continuations: extractContinuations(contextTx),
|
||||
};
|
||||
const method = getMethodName(context);
|
||||
const handler = getMethodHandler(contractModule, method);
|
||||
const txs = await handler(context);
|
||||
writeToResultFile(txs);
|
||||
}
|
||||
3
packages/cwait/src/contract-kit/quickjs/os.d.ts
vendored
Normal file
3
packages/cwait/src/contract-kit/quickjs/os.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
declare namespace os {
|
||||
function readdir(path: string): [any[], number];
|
||||
}
|
||||
3
packages/cwait/src/contract-kit/quickjs/std.d.ts
vendored
Normal file
3
packages/cwait/src/contract-kit/quickjs/std.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
declare namespace std {
|
||||
function open(path: string, mode: string): any;
|
||||
}
|
||||
11
packages/cwait/src/contract-kit/store.d.ts
vendored
Normal file
11
packages/cwait/src/contract-kit/store.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
declare module '@coinweb/contract-kit/dist/esm/operations/store' {
|
||||
export * from '@coinweb/contract-kit/dist/types/operations/store';
|
||||
}
|
||||
|
||||
declare module '@coinweb/contract-kit/dist/esm/context' {
|
||||
export * from '@coinweb/contract-kit/dist/types/context';
|
||||
}
|
||||
|
||||
declare module '@coinweb/contract-kit/dist/esm/method' {
|
||||
export * from '@coinweb/contract-kit/dist/types/method';
|
||||
}
|
||||
7
packages/cwait/src/contract-kit/types.ts
Normal file
7
packages/cwait/src/contract-kit/types.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Context, NewTx } from '@coinweb/contract-kit';
|
||||
|
||||
export type MethodCallback = (context: Context) => Promise<NewTx[]> | NewTx[];
|
||||
|
||||
export type ContractHandlers = {
|
||||
handlers: { [key: string]: MethodCallback };
|
||||
};
|
||||
17
packages/cwait/src/contract-kit/wrappers.ts
Normal file
17
packages/cwait/src/contract-kit/wrappers.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Context, isSelfCall } from '@coinweb/contract-kit';
|
||||
|
||||
import { MethodCallback } from './types';
|
||||
|
||||
/**
|
||||
* Wraps a method callback to ensure that it can only be called by the contract itself.
|
||||
* @param handler - The method callback to wrap.
|
||||
* @returns A new method callback that throws an error if the call is not from the contract itself.
|
||||
*/
|
||||
export function selfCallWrapper(handler: MethodCallback): MethodCallback {
|
||||
return async (context: Context) => {
|
||||
if (!isSelfCall(context)) {
|
||||
throw new Error('Only contract itself can call it');
|
||||
}
|
||||
return handler(context);
|
||||
};
|
||||
}
|
||||
3
packages/cwait/src/index.ts
Normal file
3
packages/cwait/src/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './contract-kit';
|
||||
export * from './onchain';
|
||||
export * from './types';
|
||||
@ -2,28 +2,26 @@ import { constructContractIssuer, Context, extractUser, getAuthenticated, getCon
|
||||
|
||||
let rawContext: Context | null = null;
|
||||
|
||||
export const setContext = (ctx: Context) => {
|
||||
export const setRawContext = (ctx: Context) => {
|
||||
rawContext = ctx;
|
||||
};
|
||||
|
||||
export const getContext = () => rawContext;
|
||||
|
||||
const useContext = <T>(cb: (ctx: Context) => T) => {
|
||||
export const getRawContext = () => {
|
||||
if (!rawContext) {
|
||||
throw new Error('Context not set');
|
||||
}
|
||||
|
||||
return cb(rawContext);
|
||||
return rawContext;
|
||||
};
|
||||
|
||||
export const context = {
|
||||
get issuer() {
|
||||
return useContext((ctx) => constructContractIssuer(getContractId(ctx.tx)));
|
||||
return constructContractIssuer(getContractId(getRawContext().tx));
|
||||
},
|
||||
get authenticated() {
|
||||
return useContext((ctx) => getAuthenticated(ctx.tx));
|
||||
return getAuthenticated(getRawContext().tx);
|
||||
},
|
||||
get user() {
|
||||
return useContext((ctx) => extractUser(getAuthenticated(ctx.tx)));
|
||||
return extractUser(getAuthenticated(getRawContext().tx));
|
||||
},
|
||||
};
|
||||
|
||||
84
packages/cwait/src/onchain/executor.ts
Normal file
84
packages/cwait/src/onchain/executor.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import {
|
||||
Context,
|
||||
extractContractArgs,
|
||||
NewTx,
|
||||
ResolvedOperation,
|
||||
getMethodArguments,
|
||||
constructContinueTx,
|
||||
constructContractRef,
|
||||
} from '@coinweb/contract-kit';
|
||||
import { getCallParameters, queue } from 'lib/onchain';
|
||||
|
||||
import { context, getRawContext, setRawContext } from './context';
|
||||
import { getAwaitedOps } from './ops/awaited';
|
||||
import { pushResolvedOp } from './ops/resolved';
|
||||
|
||||
let abortExecution: (() => void) | null = null;
|
||||
|
||||
const handleState = () => {
|
||||
const ctx = getRawContext();
|
||||
|
||||
const resolvedOps = extractContractArgs(ctx.tx);
|
||||
const currentArgs = getMethodArguments(ctx) as [unknown, unknown[], ResolvedOperation[]];
|
||||
|
||||
const initialArgs = currentArgs[1];
|
||||
const allResolvedOps = [...currentArgs[2], ...resolvedOps];
|
||||
|
||||
pushResolvedOp(allResolvedOps);
|
||||
|
||||
return { args: initialArgs, methodName: currentArgs[0] as string, ops: allResolvedOps };
|
||||
};
|
||||
|
||||
export const executor =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(method: (...args: any[]) => Promise<void>) =>
|
||||
async (ctx: Context): Promise<NewTx[]> => {
|
||||
setRawContext(ctx);
|
||||
|
||||
const { args, methodName, ops } = handleState();
|
||||
|
||||
const execution = new Promise<void>((resolve, reject) => {
|
||||
abortExecution = resolve;
|
||||
|
||||
method(...args).then(resolve, reject);
|
||||
});
|
||||
|
||||
await execution;
|
||||
|
||||
const { authInfo, availableCweb } = getCallParameters(ctx);
|
||||
|
||||
const awaitedOps = getAwaitedOps();
|
||||
|
||||
if (!awaitedOps.length) {
|
||||
return queue.gateway.unlock(ctx);
|
||||
}
|
||||
|
||||
const txFee = 700n + BigInt(awaitedOps.length) * 100n;
|
||||
|
||||
return [
|
||||
constructContinueTx(ctx, awaitedOps, [
|
||||
{
|
||||
callInfo: {
|
||||
ref: constructContractRef(context.issuer, []),
|
||||
methodInfo: {
|
||||
methodName,
|
||||
methodArgs: [args, ops],
|
||||
},
|
||||
contractInfo: {
|
||||
providedCweb: availableCweb - txFee,
|
||||
authenticated: authInfo,
|
||||
},
|
||||
contractArgs: [],
|
||||
},
|
||||
},
|
||||
]),
|
||||
];
|
||||
};
|
||||
|
||||
export const abort = () => {
|
||||
if (!abortExecution) {
|
||||
throw new Error('Abort not found');
|
||||
}
|
||||
|
||||
abortExecution();
|
||||
};
|
||||
@ -0,0 +1,3 @@
|
||||
export * from './context';
|
||||
export * from './executor';
|
||||
export * from './ops';
|
||||
@ -2,7 +2,7 @@ import { Claim, ClaimKey, constructRead, extractRead, isResolvedRead } from '@co
|
||||
|
||||
import { TypedClaim } from '../../types';
|
||||
import { context } from '../context';
|
||||
import { signal } from '../signal';
|
||||
import { abort } from '../executor';
|
||||
|
||||
import { pushAwaitedOp } from './awaited';
|
||||
import { shiftResolvedOp } from './resolved';
|
||||
@ -16,12 +16,12 @@ export const readOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
|
||||
throw new Error('Read operation not found');
|
||||
}
|
||||
|
||||
return new Promise<TClaim | null>((resolve, reject) => {
|
||||
return new Promise<TClaim | null>((resolve) => {
|
||||
if (isOp) {
|
||||
const claim = op && ((extractRead(op)?.[0] ?? null) as TClaim | null);
|
||||
resolve(claim);
|
||||
} else {
|
||||
reject(signal);
|
||||
abort();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Claim, constructStore, isResolvedStore } from '@coinweb/contract-kit';
|
||||
import { extractStore } from '@coinweb/contract-kit/dist/types/operations/store';
|
||||
import { extractStore } from '@coinweb/contract-kit/dist/esm/operations/store';
|
||||
|
||||
import { signal } from '../signal';
|
||||
import { abort } from '../executor';
|
||||
|
||||
import { pushAwaitedOp } from './awaited';
|
||||
import { shiftResolvedOp } from './resolved';
|
||||
@ -21,11 +21,11 @@ export const storeOp = (claim: Claim) => {
|
||||
throw new Error('Wrong store operation');
|
||||
}
|
||||
|
||||
return new Promise<Claim>((resolve, reject) => {
|
||||
return new Promise<Claim>((resolve) => {
|
||||
if (isOp) {
|
||||
resolve(result);
|
||||
} else {
|
||||
reject(signal);
|
||||
abort();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { constructTake, extractTake, isResolvedTake, Claim, ClaimKey } from '@coinweb/contract-kit';
|
||||
|
||||
import { TypedClaim } from '../../types';
|
||||
import { signal } from '../signal';
|
||||
import { abort } from '../executor';
|
||||
|
||||
import { pushAwaitedOp } from './awaited';
|
||||
import { shiftResolvedOp } from './resolved';
|
||||
@ -15,12 +15,12 @@ export const takeOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
|
||||
throw new Error('Take operation not found');
|
||||
}
|
||||
|
||||
return new Promise<TClaim | null>((resolve, reject) => {
|
||||
return new Promise<TClaim | null>((resolve) => {
|
||||
if (isOp) {
|
||||
const claim = op && extractTake(op);
|
||||
resolve(claim as TClaim | null);
|
||||
} else {
|
||||
reject(signal);
|
||||
abort();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -1 +0,0 @@
|
||||
export const signal = Symbol('signal');
|
||||
@ -1,13 +1,45 @@
|
||||
import { ContractCall, constructContractIssuer, prepareQueueContractCall } from '@coinweb/contract-kit';
|
||||
import {
|
||||
ContractCall,
|
||||
constructContractIssuer,
|
||||
constructSelfRegisterKey,
|
||||
constructSingleReadClaim,
|
||||
prepareQueueContractCall,
|
||||
} from '@coinweb/contract-kit';
|
||||
|
||||
export const constructCall = (
|
||||
contractId: string,
|
||||
methodName: string,
|
||||
methodArgs: unknown[],
|
||||
cost: bigint,
|
||||
auth: boolean = true
|
||||
): ContractCall => {
|
||||
import { toHex } from '../../../shared';
|
||||
|
||||
export const constructCall = ({
|
||||
contractId,
|
||||
methodName,
|
||||
methodArgs,
|
||||
cost,
|
||||
auth = true,
|
||||
withQueue = true,
|
||||
}: {
|
||||
contractId: string;
|
||||
methodName: string;
|
||||
methodArgs: unknown[];
|
||||
cost: bigint;
|
||||
auth?: boolean;
|
||||
withQueue?: boolean;
|
||||
}): ContractCall => {
|
||||
const issuer = constructContractIssuer(contractId);
|
||||
|
||||
if (!withQueue) {
|
||||
const contractCall: ContractCall = {
|
||||
contract_input: {
|
||||
data: [methodName, ...methodArgs],
|
||||
cost: toHex(cost),
|
||||
authenticated: auth,
|
||||
},
|
||||
contract_ref: {
|
||||
explicit: [],
|
||||
stored: [constructSingleReadClaim(constructContractIssuer(contractId), constructSelfRegisterKey())],
|
||||
},
|
||||
};
|
||||
|
||||
return contractCall;
|
||||
}
|
||||
|
||||
return prepareQueueContractCall(issuer, { methodName, methodArgs }, cost, auth);
|
||||
};
|
||||
|
||||
@ -10,7 +10,6 @@ import {
|
||||
QueueInput,
|
||||
} from '@coinweb/contract-kit';
|
||||
import { DataUnverified } from '@coinweb/contract-kit/dist/types/operations/data';
|
||||
import { HexBigInt, toHex32 } from 'cwap-cm-lib/shared';
|
||||
|
||||
import {
|
||||
checkIsNewHistoryAccessId,
|
||||
@ -21,6 +20,7 @@ import {
|
||||
validateMetadata,
|
||||
} from '../../module/history/onchain';
|
||||
import { ContractCallMetadataInterface, HISTORY_CODES, HistoryItem } from '../../module/history/shared';
|
||||
import { HexBigInt, toHex32 } from '../../shared';
|
||||
import { TX_STATUS_ERROR } from '../constants';
|
||||
import { Exception } from '../features/exception';
|
||||
import { queue, queueUnlockFee } from '../features/queue';
|
||||
|
||||
@ -16,8 +16,8 @@ import {
|
||||
MethodCallback,
|
||||
ResolvedOperation,
|
||||
} from '@coinweb/contract-kit';
|
||||
import { toHex32 } from 'cwap-cm-lib/shared';
|
||||
|
||||
import { toHex32 } from '../../shared';
|
||||
import { Logs } from '../constants';
|
||||
|
||||
const normalizeData = (data: unknown) => {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Queue } from '@coinweb/contract-kit';
|
||||
|
||||
export const queue = new Queue({ name: 'c1', executionDepth: 2 });
|
||||
export const queue = new Queue({ name: 'queue', executionDepth: 2 });
|
||||
|
||||
export const queueUnlockFee = 3000n;
|
||||
|
||||
@ -1,2 +1,4 @@
|
||||
VITE_API_URL='https://api-cloud.coinweb.io/wallet'
|
||||
VITE_EXPLORER_URL='https://explorer.coinweb.io'
|
||||
|
||||
VITE_CONTRACT_ADDRESS="0xc8ed7479667e1b1a9223db34e6a91b3970c7f82686ed0712fce89117a10b77ec"
|
||||
@ -17,6 +17,7 @@
|
||||
"@coinweb/webapp-library": "0.1.6",
|
||||
"axios": "^1.7.2",
|
||||
"contract.cm": "workspaces:*",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.22.3",
|
||||
|
||||
@ -1,7 +1,56 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { constructAddWordUiCommand } from 'contract.cm';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
|
||||
export const App = () => {
|
||||
const [word, setWord] = useState('');
|
||||
const [qrCode, setQrCode] = useState('');
|
||||
|
||||
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
setQrCode(constructAddWordUiCommand({ word, contractId: import.meta.env.VITE_CONTRACT_ADDRESS ?? '' }));
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Hello World</h1>
|
||||
<form onSubmit={onSubmit}>
|
||||
<div className="mx-auto my-10 flex max-w-2xl flex-col gap-2">
|
||||
<label htmlFor="first_name" className="mb-2 block text-sm font-medium text-gray-900 dark:text-white">
|
||||
Word
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="first_name"
|
||||
className="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-blue-500 dark:focus:ring-blue-500"
|
||||
placeholder="Happiness"
|
||||
required
|
||||
value={word}
|
||||
onChange={(e) => setWord(e.target.value)}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full self-end rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300 sm:w-auto dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div className="flex w-full justify-center py-4">
|
||||
<QRCodeSVG
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(qrCode).catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}}
|
||||
value={qrCode}
|
||||
size={320}
|
||||
level="L"
|
||||
className="hover:cursor-pointer"
|
||||
bgColor="transparent"
|
||||
fgColor="black"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -4,24 +4,11 @@ import path from 'node:path';
|
||||
|
||||
import YAML from 'yaml';
|
||||
|
||||
const BaseContractTemplate = 'dex-app.cm';
|
||||
const MarketMakerContractTemplate = 'market-maker.cm';
|
||||
|
||||
const ParamsPatternMatching = [
|
||||
['VITE_L2_OWNER_MIN_FEE', 'owner_min_fee'],
|
||||
['VITE_L2_OWNER_PERCENTAGE_FEE', 'owner_percentage_fee'],
|
||||
['VITE_L2_COLLATERAL_PERCENTAGE', 'collateral_percentage'],
|
||||
// ['VITE_L1_CONTRACT_ADDRESS', 'l1_contract_address'],
|
||||
];
|
||||
|
||||
const ContractIdPattern = 'VITE_L2_CONTRACT_ADDRESS';
|
||||
|
||||
const TemplatePatternMatching = [
|
||||
['_BASE_', BaseContractTemplate],
|
||||
['_MAKER_', MarketMakerContractTemplate],
|
||||
];
|
||||
|
||||
const Variants = [['eth'], ['bnb'], ['btc'], ['trx'], ['eth', 'usdt'], ['bnb', 'usdt'], ['trx', 'usdt']];
|
||||
const ContractIdPattern = 'VITE_CONTRACT_ADDRESS';
|
||||
|
||||
const updated = [];
|
||||
|
||||
@ -51,27 +38,10 @@ function updateValue(line, value) {
|
||||
}
|
||||
|
||||
function updateLine(line, parameters, index) {
|
||||
const templatePattern = TemplatePatternMatching.find(([pattern]) => isMatch(line, pattern));
|
||||
const variant = Variants.filter((variant) => variant.every((pattern) => isMatch(line, pattern))).sort(
|
||||
({ length: a }, { length: b }) => (a < b ? 1 : -1)
|
||||
)[0];
|
||||
|
||||
if (!templatePattern || !variant) {
|
||||
return line;
|
||||
}
|
||||
|
||||
const paramPattern = ParamsPatternMatching.find(([pattern]) => isMatch(line, pattern));
|
||||
|
||||
if (paramPattern) {
|
||||
const instanceParameters = parameters.find(
|
||||
({ alias, template }) =>
|
||||
isMatch(template, templatePattern[1]) && variant.every((pattern) => isMatch(alias, pattern))
|
||||
);
|
||||
|
||||
if (instanceParameters) {
|
||||
const value = Object.entries(instanceParameters.parameters.content).find(([name]) =>
|
||||
isMatch(name, paramPattern[1])
|
||||
)?.[1];
|
||||
const value = Object.entries(parameters.parameters.content).find(([name]) => isMatch(name, paramPattern[1]))?.[1];
|
||||
|
||||
if (value !== undefined) {
|
||||
const updatedLine = updateValue(line, value);
|
||||
@ -83,16 +53,13 @@ function updateLine(line, parameters, index) {
|
||||
return updatedLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isMatch(line, ContractIdPattern)) {
|
||||
const templates = Object.entries(index).filter(([name]) => isMatch(name, templatePattern[1]));
|
||||
const instances = templates.find((template) => template[1].target_instances.length)?.[1].target_instances;
|
||||
const instances = Object.entries(index).find((template) => template[1].target_instances.length)?.[1]
|
||||
.target_instances;
|
||||
|
||||
if (instances?.length) {
|
||||
const contractId = instances.find(({ alias }) =>
|
||||
variant.every((pattern) => isMatch(alias, pattern))
|
||||
)?.instance_id;
|
||||
const contractId = instances[0]?.instance_id;
|
||||
|
||||
if (contractId !== undefined) {
|
||||
const updatedLine = updateValue(line, '0x' + contractId);
|
||||
@ -151,7 +118,7 @@ function printResults() {
|
||||
throw new Error('Cannot find config for profile', profile);
|
||||
}
|
||||
|
||||
const envFilePath = path.resolve('packages/dapp-ui', envFileName);
|
||||
const envFilePath = path.resolve('packages/ui', envFileName);
|
||||
|
||||
const env = fs.readFileSync(envFilePath, 'utf-8');
|
||||
if (!env) {
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@ -6970,6 +6970,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"qrcode.react@npm:^4.2.0":
|
||||
version: 4.2.0
|
||||
resolution: "qrcode.react@npm:4.2.0"
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
checksum: 10c0/68c691d130e5fda2f57cee505ed7aea840e7d02033100687b764601f9595e1116e34c13876628a93e1a5c2b85e4efc27d30b2fda72e2050c02f3e1c4e998d248
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"qs@npm:^6.12.3":
|
||||
version: 6.14.0
|
||||
resolution: "qs@npm:6.14.0"
|
||||
@ -8702,6 +8711,7 @@ __metadata:
|
||||
jsdom: "npm:^24.0.0"
|
||||
postcss: "npm:^8.4.39"
|
||||
postcss-cli: "npm:^11.0.0"
|
||||
qrcode.react: "npm:^4.2.0"
|
||||
react: "npm:^18.2.0"
|
||||
react-dom: "npm:^18.2.0"
|
||||
react-router-dom: "npm:^6.22.3"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user