feat: add packages with initial structure
This commit is contained in:
parent
e3c9659af8
commit
c5237698cd
@ -19,8 +19,6 @@ use:
|
||||
- jump-forwarder.cm v0.1.5
|
||||
- jump_forwarder_devnet v0.1.5
|
||||
|
||||
|
||||
|
||||
interpreters: {}
|
||||
|
||||
contract_templates:
|
||||
@ -33,4 +31,3 @@ contract_instances:
|
||||
template: contract.cm v0.0.1
|
||||
parameters:
|
||||
content: []
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
"build:production": "yarn build:cm && yarn workspace dapp-ui build:production",
|
||||
"build:lib": "yarn workspaces foreach -Ap --include 'packages/lib' --include 'packages/cwait' run build",
|
||||
"build:cm": "yarn build:lib && yarn workspaces foreach -Ap --include 'packages/*.cm' run build",
|
||||
"build:non-cm": "yarn workspaces foreach -Ap --include 'packages/*' --exclude 'packages/*.cm' --exclude 'packages/lib' --exclude 'packages/cwait' run build",
|
||||
"build:non-cm": "yarn workspaces foreach -Ap --include 'packages/*' --exclude 'packages/*.cm' --exclude 'packages/*.ignore' --exclude 'packages/lib' --exclude 'packages/cwait' run build",
|
||||
"create-index": "cweb-tool create-index -c ./.cweb-config/config.yaml --profile $REGISTRATION_PROFILE",
|
||||
"publish-index": "cweb-tool publish-index -c ./.cweb-config/config.yaml --profile $REGISTRATION_PROFILE",
|
||||
"deploy-contracts": "yarn build:cm && yarn publish-actions",
|
||||
@ -39,7 +39,7 @@
|
||||
"g:lint": "cd $INIT_CWD && eslint",
|
||||
"g:vitest": "cd $INIT_CWD && vitest",
|
||||
"g:lint-staged": "cd $INIT_CWD && lint-staged",
|
||||
"publish:lib": "yarn workspaces foreach -Ap --include 'packages/cwap-cm-*' run publish:lib"
|
||||
"publish:lib": "yarn workspaces foreach -Ap --include 'packages/lib' run publish:lib"
|
||||
},
|
||||
"resolutions": {
|
||||
"@coinweb/cweb-tool": "2.0.22",
|
||||
|
||||
37
packages/btc-like-provider.cm.ignore/package.json
Normal file
37
packages/btc-like-provider.cm.ignore/package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "btc-like-provider.cm",
|
||||
"version": "0.0.1-dev",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "yarn build:files && yarn pack:all",
|
||||
"build:files": "yarn clean && yarn g:tsc -p tsconfig.build.json && NODE_ENV=production ./scripts/build.sh",
|
||||
"start": "node src/offchain/index.js",
|
||||
"test": "yarn g:vitest run --pool=forks",
|
||||
"test:prepare": "mkdir -p tests_data && cp ../../.cweb_tool/simulation/unknown.json tests_data/state.json && cp ../../.dapp-ecosystem-lock-test.yaml tests_data/index.yaml",
|
||||
"test:watch": "yarn g:vitest",
|
||||
"test:coverage": "yarn g:vitest run --coverage",
|
||||
"pack:relink": "cd $INIT_CWD && node scripts/package-relink.js",
|
||||
"pack:all": "yarn pack:cweb && yarn pack:relink && yarn pack:yarn && yarn pack:relink",
|
||||
"pack:cweb": "yarn g:cweb-tool pack . dist/out ../../.cweb-config/cweb-pack.yaml -c ../../.cweb-config/config.yaml --profile $REGISTRATION_PROFILE",
|
||||
"pack:yarn": "cd dist/out && touch yarn.lock && yarn pack -o my-contract-module.tgz",
|
||||
"clean": "rm -rf cweb_dist dist .calls.yaml",
|
||||
"typecheck": "yarn g:tsc --noEmit",
|
||||
"dev": "yarn g:tsc -p tsconfig.dev.json --watch",
|
||||
"lint": "yarn g:lint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@coinweb/contract-kit": "0.2.6",
|
||||
"@coinweb/self-register": "0.1.3",
|
||||
"@noble/hashes": "1.4.0",
|
||||
"bech32": "2.0.0",
|
||||
"bs58": "6.0.0",
|
||||
"lib": "workspaces:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.20.2"
|
||||
},
|
||||
"main": "cweb_dist/offchain/index.js",
|
||||
"engines": {
|
||||
"cweb_interpreter": "a344c6003922f9e44385f6e8234a7d2567d9a676b14330ad3b42cbd1948a92bf"
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,3 @@
|
||||
export * from './api';
|
||||
export * from './uiCommands';
|
||||
export * from './shared';
|
||||
export * from '../shared';
|
||||
@ -1,6 +1,6 @@
|
||||
import { constructCall, constructUiCommand } from 'lib/offchain';
|
||||
|
||||
import { AddWordArgs, FEE, PUBLIC_METHODS } from './shared';
|
||||
import { AddWordArgs, FEE, PUBLIC_METHODS } from '../shared';
|
||||
|
||||
export const constructAddWordUiCommand = ({ word, contractId }: { word: string; contractId: string }) => {
|
||||
return constructUiCommand([
|
||||
@ -1,6 +1,6 @@
|
||||
import { constructCwebMain } from 'cwait';
|
||||
|
||||
import { PUBLIC_METHODS } from '../offchain/shared';
|
||||
import { PUBLIC_METHODS } from '../shared';
|
||||
|
||||
import { addWord } from './addWord';
|
||||
|
||||
@ -0,0 +1,96 @@
|
||||
export enum Key {
|
||||
ACTIVE_INDEX = 'ACTIVE_INDEX',
|
||||
MAKER_INDEX = 'MAKER_INDEX',
|
||||
DATE_INDEX = 'DATE_INDEX',
|
||||
RATE_INDEX = 'RATE_INDEX',
|
||||
|
||||
MAKER = 'MAKER',
|
||||
|
||||
ORDER = 'ORDER', //ORDER_STATE + ORDER_FUNDS
|
||||
LATEST_ORDER_ID = 'LATEST_ORDER_ID', //INCREMENT_INDEX
|
||||
ORDER_DIRECTION_INDEX = 'ORDER_DIRECTION_INDEX',
|
||||
|
||||
PACT = 'PACT', //ORDER_STATE + ORDER_COLLATERAL
|
||||
LATEST_PACT_ID = 'LATEST_PACT_ID', //INCREMENT_INDEX
|
||||
PACT_PENALTY_INDEX = 'PACT_PENALTY_INDEX',
|
||||
|
||||
SWAP_INFO = 'SWAP_INFO', //L1_TX_INFO
|
||||
PAYMENT_NONCE = 'PAYMENT_NONCE', //BTC_NONCE
|
||||
UNIQUE_VALUE = 'UNIQUE_VALUE',
|
||||
FEE_POOL_ADDRESS = 'FEE_POOL_ADDRESS',
|
||||
}
|
||||
|
||||
export enum PUBLIC_METHODS {
|
||||
CREATE_ORDERS = 'CREATE_ORDERS',
|
||||
CANCEL_ORDERS = 'CANCEL_ORDERS',
|
||||
DEPOSIT_COLLATERAL = 'DEPOSIT_COLLATERAL',
|
||||
WITHDRAW_COLLATERAL = 'WITHDRAW_COLLATERAL',
|
||||
}
|
||||
|
||||
export const FEE: Record<`${PUBLIC_METHODS}` | 'CHANGE_FEE_POOL_ADDRESS', bigint> = {
|
||||
CREATE_ORDERS: 10000000n,
|
||||
CANCEL_ORDERS: 10000000n,
|
||||
DEPOSIT_COLLATERAL: 10000000n,
|
||||
WITHDRAW_COLLATERAL: 10000000n,
|
||||
CHANGE_FEE_POOL_ADDRESS: 10000000n,
|
||||
};
|
||||
|
||||
export enum ORDER_STATUS {
|
||||
ACTIVE = 'ACTIVE',
|
||||
DEACTIVATED = 'DEACTIVATED',
|
||||
DISABLED = 'DISABLED',
|
||||
}
|
||||
|
||||
export enum PACT_STATUS {
|
||||
ACTIVE = 'ACTIVE',
|
||||
DISABLED = 'DISABLED',
|
||||
}
|
||||
|
||||
export enum AddressEncoding {
|
||||
Hex = 'Hex',
|
||||
Base58 = 'Base58',
|
||||
Bech32 = 'Bech32',
|
||||
Bech32m = 'Bech32m',
|
||||
}
|
||||
|
||||
export enum ProviderType {
|
||||
Evm = 'Evm',
|
||||
Btc = 'Btc',
|
||||
}
|
||||
|
||||
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 = 'btc',
|
||||
tbtc = 'tbtc',
|
||||
}
|
||||
|
||||
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)[];
|
||||
3
packages/btc-like-provider.cm.ignore/src/shared/index.ts
Normal file
3
packages/btc-like-provider.cm.ignore/src/shared/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './keys';
|
||||
export * from './constants/constants';
|
||||
export * from './types';
|
||||
121
packages/btc-like-provider.cm.ignore/src/shared/types.ts
Normal file
121
packages/btc-like-provider.cm.ignore/src/shared/types.ts
Normal file
@ -0,0 +1,121 @@
|
||||
import type { HexString, User } from '@coinweb/contract-kit';
|
||||
import { HexBigInt } from 'lib/shared';
|
||||
|
||||
import { ORDER_STATUS, OrderBatchFields, AddressEncoding } from './constants/constants';
|
||||
|
||||
export type ProviderData = unknown;
|
||||
|
||||
export type BtcProviderData = {
|
||||
l1TxId: string;
|
||||
vout: number;
|
||||
psbt: string;
|
||||
};
|
||||
|
||||
export type DirectionParameter = {
|
||||
provider: string;
|
||||
providerData: ProviderData;
|
||||
value: HexBigInt;
|
||||
};
|
||||
|
||||
export type Direction = {
|
||||
from: DirectionParameter;
|
||||
to: DirectionParameter;
|
||||
};
|
||||
|
||||
export type OrderStateClaimBody = {
|
||||
recipient: string;
|
||||
cwebAmount: HexBigInt;
|
||||
minCwebSwapAmount: HexBigInt;
|
||||
directions: Direction[];
|
||||
createdAt: number;
|
||||
expirationDate: number;
|
||||
status: ORDER_STATUS;
|
||||
parentTxId: string;
|
||||
history: HistoryAccess;
|
||||
maker: User;
|
||||
};
|
||||
|
||||
export type SwapInfoData = {
|
||||
l1TxId: string;
|
||||
recipientAddress: string;
|
||||
backPayAddress: string;
|
||||
amount: HexBigInt;
|
||||
l2TxId: string;
|
||||
};
|
||||
|
||||
export type SwapToBtcL1Payload = {
|
||||
minL1Amount: HexBigInt;
|
||||
promisedL1Amount: HexBigInt;
|
||||
l1Recipient: HexString;
|
||||
fallbackRecipient: HexString;
|
||||
};
|
||||
|
||||
export type SwapToEvmL1Payload = {
|
||||
minL1Amount: HexBigInt;
|
||||
promisedL1Amount: HexBigInt;
|
||||
l1Recipient: HexString;
|
||||
};
|
||||
|
||||
export type SwapToEvmPreset = {
|
||||
toL1ChainType: L1Types.Evm;
|
||||
c2ContractId: HexString;
|
||||
c2ContractMethod: HexString;
|
||||
fallbackC1ContractId: HexString;
|
||||
fallbackC1ContractMethod: HexString;
|
||||
};
|
||||
|
||||
export type SwapToBtcPreset = {
|
||||
toL1ChainType: L1Types.Btc;
|
||||
c2ContractId: HexString;
|
||||
c2ContractMethod: HexString;
|
||||
encoding: AddressEncoding;
|
||||
};
|
||||
|
||||
export type SwapPreset = SwapToEvmPreset | SwapToBtcPreset;
|
||||
|
||||
export type CreateOrderBaseParams = {
|
||||
cwebAmount?: bigint;
|
||||
minCwebSwapAmount?: bigint;
|
||||
directions: Direction[];
|
||||
};
|
||||
|
||||
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 = {
|
||||
bech32: string;
|
||||
scriptHash: number;
|
||||
};
|
||||
@ -1,13 +0,0 @@
|
||||
export enum Key {
|
||||
WORD = 'WORD',
|
||||
SET = 'SET',
|
||||
BY_LETTER = 'BY_LETTER',
|
||||
}
|
||||
|
||||
export enum PUBLIC_METHODS {
|
||||
ADD_WORD = 'ADD_WORD',
|
||||
}
|
||||
|
||||
export const FEE = {
|
||||
ADD_WORD: 10000000n,
|
||||
};
|
||||
@ -1,29 +0,0 @@
|
||||
import type { ClaimKey } from '@coinweb/contract-kit';
|
||||
|
||||
import { Key } from './constants';
|
||||
|
||||
/* FirstPart */
|
||||
export const createWordFirstPart = () => [Key.WORD];
|
||||
|
||||
export const createByLetterFirstPart = (letter: string) => [Key.BY_LETTER, letter];
|
||||
|
||||
export const createSetFirstPart = () => [Key.SET];
|
||||
|
||||
/* Key */
|
||||
export const createWordKey = (id: string) =>
|
||||
({
|
||||
first_part: createWordFirstPart(),
|
||||
second_part: [id],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createByLetterKey = (letter: string, id: string) =>
|
||||
({
|
||||
first_part: createByLetterFirstPart(letter),
|
||||
second_part: [id],
|
||||
}) satisfies ClaimKey;
|
||||
|
||||
export const createSetKey = (letter: string) =>
|
||||
({
|
||||
first_part: createSetFirstPart(),
|
||||
second_part: [letter],
|
||||
}) satisfies ClaimKey;
|
||||
@ -1,9 +0,0 @@
|
||||
export type SetClaimBody = {
|
||||
set: string;
|
||||
};
|
||||
|
||||
export type WordClaimBody = {
|
||||
word: string;
|
||||
};
|
||||
|
||||
export type AddWordArgs = [string];
|
||||
1
packages/evm-provider.cm.ignore/.gitignore
vendored
Normal file
1
packages/evm-provider.cm.ignore/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
deploy/calls.yaml
|
||||
12
packages/evm-provider.cm.ignore/deploy/calls.yaml.template
Normal file
12
packages/evm-provider.cm.ignore/deploy/calls.yaml.template
Normal file
@ -0,0 +1,12 @@
|
||||
# this is the contract id
|
||||
__CWEB_CONTRACT_SELF_REFERENCE__:
|
||||
# out contract does not take any arguments, so we pass an empty object
|
||||
args:
|
||||
- "CREATE_ORDER"
|
||||
- "0x000000000000000000000000000000000000000000000001236efcbcbb340000"
|
||||
- "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
|
||||
- "0x9A4250b8c30Ca3cC5Dc33Ddbe30f71509a2E60a5"
|
||||
- "0x00000000000000000000000000000000000000000000000002ea11e32ad50000"
|
||||
- "0x00000000000000000000000000000000000000000000000000000000000186a0"
|
||||
cweb_provided: "0x00000000000000000000000000000000000000000000000126590e9fe60a86a0"
|
||||
auth: true
|
||||
37
packages/evm-provider.cm.ignore/package.json
Normal file
37
packages/evm-provider.cm.ignore/package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "evm-provider.cm",
|
||||
"version": "0.0.1-dev",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "yarn build:files && yarn pack:all",
|
||||
"build:files": "yarn clean && yarn g:tsc -p tsconfig.build.json && NODE_ENV=production ./scripts/build.sh",
|
||||
"start": "node src/offchain/index.js",
|
||||
"test": "yarn g:vitest run --pool=forks",
|
||||
"test:prepare": "mkdir -p tests_data && cp ../../.cweb_tool/simulation/unknown.json tests_data/state.json && cp ../../.dapp-ecosystem-lock-test.yaml tests_data/index.yaml",
|
||||
"test:watch": "yarn g:vitest",
|
||||
"test:coverage": "yarn g:vitest run --coverage",
|
||||
"pack:relink": "cd $INIT_CWD && node scripts/package-relink.js",
|
||||
"pack:all": "yarn pack:cweb && yarn pack:relink && yarn pack:yarn && yarn pack:relink",
|
||||
"pack:cweb": "yarn g:cweb-tool pack . dist/out ../../.cweb-config/cweb-pack.yaml -c ../../.cweb-config/config.yaml --profile $REGISTRATION_PROFILE",
|
||||
"pack:yarn": "cd dist/out && touch yarn.lock && yarn pack -o my-contract-module.tgz",
|
||||
"clean": "rm -rf cweb_dist dist .calls.yaml",
|
||||
"typecheck": "yarn g:tsc --noEmit",
|
||||
"dev": "yarn g:tsc -p tsconfig.dev.json --watch",
|
||||
"lint": "yarn g:lint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@coinweb/contract-kit": "0.2.6",
|
||||
"@coinweb/self-register": "0.1.3",
|
||||
"@noble/hashes": "1.4.0",
|
||||
"bech32": "2.0.0",
|
||||
"bs58": "6.0.0",
|
||||
"lib": "workspaces:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.20.2"
|
||||
},
|
||||
"main": "cweb_dist/offchain/index.js",
|
||||
"engines": {
|
||||
"cweb_interpreter": "a344c6003922f9e44385f6e8234a7d2567d9a676b14330ad3b42cbd1948a92bf"
|
||||
}
|
||||
}
|
||||
41
packages/evm-provider.cm.ignore/scripts/build.sh
Executable file
41
packages/evm-provider.cm.ignore/scripts/build.sh
Executable file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
ROOT=$DIR/..
|
||||
|
||||
rm -rf $ROOT/{cweb_dist/{on,off}chain,dist/tmp/{step{1,2,3},final}}
|
||||
mkdir -p $ROOT/{cweb_dist/{on,off}chain,dist/tmp/{step{1,2,3},final}}
|
||||
|
||||
(
|
||||
cd $ROOT
|
||||
cp -rf dist/offchain/. cweb_dist/offchain/
|
||||
|
||||
## Bundle and transpile `index.js` so it can be understood by the quickjs interpreter:
|
||||
echo 'import {cwebMain as f} from "../../../dist/onchain/index"; f();' \
|
||||
> dist/tmp/step1/onchain.js
|
||||
|
||||
yarn esbuild \
|
||||
--bundle \
|
||||
--log-level=error \
|
||||
--format=esm \
|
||||
dist/tmp/step1/onchain.js \
|
||||
--outfile=dist/tmp/step2/onchain.js
|
||||
|
||||
echo 'import * as std from "std";' |
|
||||
cat - dist/tmp/step2/onchain.js \
|
||||
> dist/tmp/step3/onchain.js
|
||||
|
||||
yarn esbuild \
|
||||
--bundle \
|
||||
--log-level=error \
|
||||
--format=esm \
|
||||
--external:std \
|
||||
--tree-shaking=true \
|
||||
dist/tmp/step3/onchain.js \
|
||||
--outfile=dist/tmp/final/onchain.js
|
||||
|
||||
cp dist/tmp/final/onchain.js cweb_dist/onchain/index.js
|
||||
)
|
||||
|
||||
rm -rf $ROOT/dist/{tmp,offchain,onchain}
|
||||
33
packages/evm-provider.cm.ignore/scripts/package-relink.js
Normal file
33
packages/evm-provider.cm.ignore/scripts/package-relink.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const workspaceLink = 'workspaces:*';
|
||||
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
// Update target package.json
|
||||
const targetPath = resolve(__dirname, '../dist/out/package.json');
|
||||
const targetPackage = JSON.parse(readFileSync(targetPath, 'utf8'));
|
||||
|
||||
// Process all cm- dependencies
|
||||
Object.keys(targetPackage.dependencies).forEach((dependency) => {
|
||||
if (dependency.startsWith('cwap-cm-')) {
|
||||
// Read source version from the corresponding package
|
||||
const sourcePath = resolve(__dirname, `../../${dependency}/package.json`);
|
||||
try {
|
||||
const sourcePackage = JSON.parse(readFileSync(sourcePath, 'utf8'));
|
||||
const sourceVersion = sourcePackage.version;
|
||||
|
||||
if (targetPackage.dependencies[dependency] === workspaceLink) {
|
||||
targetPackage.dependencies[dependency] = sourceVersion;
|
||||
} else {
|
||||
targetPackage.dependencies[dependency] = workspaceLink;
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`Warning: Could not read package.json for ${dependency} at ${sourcePath}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Write back the updated package.json
|
||||
writeFileSync(targetPath, JSON.stringify(targetPackage, null, 2));
|
||||
41
packages/evm-provider.cm.ignore/src/offchain/api.ts
Normal file
41
packages/evm-provider.cm.ignore/src/offchain/api.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { ClaimKey } from '@coinweb/contract-kit';
|
||||
import { Client } from 'lib/offchain';
|
||||
|
||||
import { SetClaimBody, WordClaimBody } from './shared';
|
||||
import { createWordFirstPart, createSetKey, createWordKey, createByLetterFirstPart } from './shared/keys';
|
||||
|
||||
export const getWord = async (client: Client, id: string) => {
|
||||
const key = createWordKey(id);
|
||||
|
||||
const claimResponse = (await client.fetchClaims(key.first_part, key.second_part))[0];
|
||||
|
||||
const data = claimResponse.content.body as WordClaimBody;
|
||||
|
||||
return data.word;
|
||||
};
|
||||
|
||||
export const getWords = async (client: Client): Promise<string[]> => {
|
||||
const claimsResponse = await client.fetchClaims(createWordFirstPart(), null);
|
||||
|
||||
return claimsResponse.map(({ content }) => (content.body as WordClaimBody).word);
|
||||
};
|
||||
|
||||
export const getWordsByLetter = async (client: Client, letter: string): Promise<string[]> => {
|
||||
const indexResponse = await client.fetchClaims(createByLetterFirstPart(letter), null);
|
||||
|
||||
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;
|
||||
};
|
||||
3
packages/evm-provider.cm.ignore/src/offchain/index.ts
Normal file
3
packages/evm-provider.cm.ignore/src/offchain/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './api';
|
||||
export * from './uiCommands';
|
||||
export * from '../shared';
|
||||
15
packages/evm-provider.cm.ignore/src/offchain/uiCommands.ts
Normal file
15
packages/evm-provider.cm.ignore/src/offchain/uiCommands.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { constructCall, constructUiCommand } from 'lib/offchain';
|
||||
|
||||
import { AddWordArgs, FEE, PUBLIC_METHODS } from '../shared';
|
||||
|
||||
export const constructAddWordUiCommand = ({ word, contractId }: { word: string; contractId: string }) => {
|
||||
return constructUiCommand([
|
||||
constructCall({
|
||||
contractId,
|
||||
methodName: PUBLIC_METHODS.ADD_WORD,
|
||||
methodArgs: [[word] satisfies AddWordArgs],
|
||||
cost: FEE.ADD_WORD,
|
||||
withQueue: false,
|
||||
}),
|
||||
]);
|
||||
};
|
||||
@ -0,0 +1,94 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { constructContractIssuer, constructContractRef, type PreparedCallInfo } from '@coinweb/contract-kit';
|
||||
import { UnitTest, type ExecInfo, type RoundInfo, type UnitTestContext, type DbWriteOp } from '@coinweb/testing-sdk';
|
||||
import { describe, it, expect, beforeAll } from 'vitest';
|
||||
|
||||
import { AddWordArgs, FEE, PUBLIC_METHODS } from '../../offchain/shared';
|
||||
|
||||
import { CONTRACT_INSTANCE_ID, TEST_PRIVATE_KEY, TEST_PUBLIC_KEY, waitRoundsCount } from './helpers';
|
||||
|
||||
const addWordRound = (creatorAccount: Buffer): RoundInfo => {
|
||||
const self = constructContractIssuer(CONTRACT_INSTANCE_ID);
|
||||
|
||||
const kvDeleteCallInfo: PreparedCallInfo = {
|
||||
ref: constructContractRef(self, []),
|
||||
methodInfo: { methodName: PUBLIC_METHODS.ADD_WORD, methodArgs: ['TEST_HELLO'] satisfies AddWordArgs },
|
||||
contractArgs: [],
|
||||
contractInfo: { providedCweb: FEE.ADD_WORD, authenticated: null }, // null = authenticated account in tests
|
||||
};
|
||||
|
||||
const withFunds = { type: { privateKey: creatorAccount } };
|
||||
|
||||
return {
|
||||
txsInfo: {
|
||||
// @ts-ignore
|
||||
txs: [{ callInfo: kvDeleteCallInfo, withFunds }],
|
||||
l1_events: [],
|
||||
},
|
||||
claims: [],
|
||||
blocks_on: [],
|
||||
};
|
||||
};
|
||||
|
||||
const runTest = async (context: UnitTestContext, input: ExecInfo, checkFn: (results: DbWriteOp[]) => void) => {
|
||||
const test = new UnitTest(context);
|
||||
await test.load(path.join(import.meta.dirname, '../../../tests_data/state.json'));
|
||||
await test.run(input, { checkFn });
|
||||
};
|
||||
|
||||
describe('PUBLIC_METHODS.ADD_WORD Tests', () => {
|
||||
let creatorAccount: { publicKey: Buffer; privateKey: Buffer };
|
||||
|
||||
beforeAll(() => {
|
||||
creatorAccount = {
|
||||
privateKey: Buffer.from(TEST_PRIVATE_KEY, 'hex'),
|
||||
publicKey: Buffer.from(TEST_PUBLIC_KEY, 'hex'),
|
||||
};
|
||||
});
|
||||
|
||||
it('Should successfully execute', async () => {
|
||||
const input: ExecInfo = {
|
||||
rounds: [...waitRoundsCount(50), addWordRound(creatorAccount.privateKey), ...waitRoundsCount(2)],
|
||||
};
|
||||
|
||||
const checkFn = (results: DbWriteOp[]) => {
|
||||
expect(results).toBeDefined();
|
||||
|
||||
// @ts-ignore
|
||||
// const errors = findAllValuesRecursivelyByKey<{ ContractError: ContractError }>(results, 'Invalid');
|
||||
// expect(errors.length).toBe(0);
|
||||
|
||||
// @ts-ignore
|
||||
// const storeOps = findAllValuesRecursivelyByKey<CwebStore>(results, 'StoreOp');
|
||||
// expect(storeOps.length).toBeGreaterThan(0);
|
||||
|
||||
// const existingPayload = storeOps.find((s) => isEqual(s.key.first_part, createFirstPartDefault()));
|
||||
|
||||
// expect(existingPayload).toBeDefined();
|
||||
// expect(existingPayload?.key).toStrictEqual(createDefaultKey(Number.MAX_SAFE_INTEGER));
|
||||
// expect(existingPayload?.key.first_part).toStrictEqual(createFirstPartDefault());
|
||||
|
||||
// const { id, data, owner, tx } = existingPayload?.body as StoreKvPayload;
|
||||
// expect(id).toBeDefined();
|
||||
// expect(data).toBeDefined();
|
||||
// expect(owner).toBeDefined();
|
||||
// expect(tx).toBeDefined();
|
||||
// expect(tx?.timestamp).toBeDefined();
|
||||
// expect(tx?.coinwebTxId).toBeDefined();
|
||||
// expect(Number(id)).toStrictEqual(Number.MAX_SAFE_INTEGER);
|
||||
// expect(owner).toStrictEqual({
|
||||
// auth: 'EcdsaContract',
|
||||
// payload: TEST_PUBLIC_KEY,
|
||||
// });
|
||||
};
|
||||
|
||||
const context: UnitTestContext = {
|
||||
name: 'add_word',
|
||||
testPath: path.join(import.meta.dirname, './tests_data/add_word'),
|
||||
verbose: true,
|
||||
};
|
||||
|
||||
await runTest(context, input, checkFn);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,35 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { getInstanceFromIndex, type RoundInfo } from '@coinweb/testing-sdk';
|
||||
|
||||
const onchainPackage = (await import('../../../dist/out/package.json')) as {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export const CONTRACT_INSTANCE = await getInstanceFromIndex({
|
||||
path: path.resolve(import.meta.dirname, '../../../tests_data/index.yaml'),
|
||||
instance_alias: 'cwait-contract 0.0.1-test',
|
||||
});
|
||||
|
||||
export const CONTRACT_INSTANCE_ID = '0x'.concat(CONTRACT_INSTANCE.instance_id.replace(/0x/, ''));
|
||||
|
||||
export const CONTRACT_TEMPLATE_ID = `0x${onchainPackage.name.substring(5)}`;
|
||||
|
||||
export const TEST_PRIVATE_KEY = '31c70848e4e3aaffcf91f134853ec966e913aa9a813115bcb81512e7625f46a9';
|
||||
export const TEST_PUBLIC_KEY = '03951f89fe78e13f295d96eb7afa1e0da726df7d58f9c84f7144e5febc30efeec4';
|
||||
|
||||
export const waitRoundsCount = (roundsCount: number): RoundInfo[] => {
|
||||
const emptyRound: RoundInfo = {
|
||||
txsInfo: {
|
||||
txs: [],
|
||||
l1_events: [],
|
||||
},
|
||||
claims: [],
|
||||
blocks_on: [],
|
||||
};
|
||||
const rounds: RoundInfo[] = [];
|
||||
for (let i = 0; i < roundsCount; i++) {
|
||||
rounds.push(emptyRound);
|
||||
}
|
||||
return rounds;
|
||||
};
|
||||
54
packages/evm-provider.cm.ignore/src/onchain/addWord.ts
Normal file
54
packages/evm-provider.cm.ignore/src/onchain/addWord.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { constructClaim } from '@coinweb/contract-kit';
|
||||
import { readOp, storeOp, cwait } from 'cwait';
|
||||
|
||||
import { TypedClaim } from '../../../lib/dist/shared/types';
|
||||
import { AddWordArgs, createWordKey, WordClaimBody } from '../offchain/shared';
|
||||
|
||||
import { extraLogic } from './extraLogic';
|
||||
|
||||
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 < 0 ? hash * -1 : hash).toString(16)}`;
|
||||
}
|
||||
|
||||
export const addWord = cwait(async (...[word]: AddWordArgs) => {
|
||||
console.log('addWord START');
|
||||
|
||||
const id = hashCode(word);
|
||||
|
||||
console.log('await storeOp');
|
||||
await storeOp(constructClaim(createWordKey(id), { word }, '0x0'));
|
||||
|
||||
console.log('await extraLogic');
|
||||
const [wordClaim] = await Promise.all([extraLogic(id, 1), extraLogic(id, 2)]);
|
||||
|
||||
const newWord1 = (wordClaim?.body.word ?? '') + '_1';
|
||||
const newId1 = hashCode(newWord1);
|
||||
|
||||
const newWord2 = (wordClaim?.body.word ?? '') + '_2';
|
||||
const newId2 = hashCode(newWord2);
|
||||
|
||||
const newWord3 = (wordClaim?.body.word ?? '') + '_3';
|
||||
const newId3 = hashCode(newWord3);
|
||||
|
||||
console.log('free storeOp');
|
||||
storeOp(constructClaim(createWordKey(newId1), { word: wordClaim?.body.word + '_free' }, '0x0'));
|
||||
|
||||
console.log('await Promise.all');
|
||||
await Promise.all([
|
||||
storeOp(constructClaim(createWordKey(newId2), { word: wordClaim?.body.word + '_in_promise_all' }, '0x0')),
|
||||
storeOp(constructClaim(createWordKey(newId3), { word: 'WIN' }, '0x0')),
|
||||
]);
|
||||
|
||||
console.log('free readOp');
|
||||
readOp<TypedClaim<WordClaimBody>>(createWordKey(newId3));
|
||||
|
||||
console.log('addWord END');
|
||||
});
|
||||
9
packages/evm-provider.cm.ignore/src/onchain/contract.ts
Normal file
9
packages/evm-provider.cm.ignore/src/onchain/contract.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { constructCwebMain } from 'cwait';
|
||||
|
||||
import { PUBLIC_METHODS } from '../shared';
|
||||
|
||||
import { addWord } from './addWord';
|
||||
|
||||
export const cwebMain = constructCwebMain({
|
||||
[PUBLIC_METHODS.ADD_WORD]: addWord,
|
||||
});
|
||||
31
packages/evm-provider.cm.ignore/src/onchain/extraLogic.ts
Normal file
31
packages/evm-provider.cm.ignore/src/onchain/extraLogic.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { constructClaim } from '@coinweb/contract-kit';
|
||||
import { cwait, lock, readOp, storeOp, TypedClaim } from 'cwait';
|
||||
|
||||
import { createWordKey, WordClaimBody } from '../offchain';
|
||||
|
||||
import { extraLogic2 } from './extraLogic2';
|
||||
|
||||
export const extraLogic = cwait(async (id: string, i: number) => {
|
||||
console.log('extraLogic START ++ ', i);
|
||||
|
||||
console.log('extraLogic lock + ', i);
|
||||
const unlock = await lock(createWordKey(id));
|
||||
|
||||
console.log('extraLogic readOp + ', i);
|
||||
const result = await readOp<TypedClaim<WordClaimBody>>(createWordKey(id));
|
||||
|
||||
console.log('extraLogic storeOp + ', i);
|
||||
await storeOp(
|
||||
constructClaim(
|
||||
createWordKey(id),
|
||||
{ word: result?.body.word.split('').reverse().join('') + '_extraLogic + ' + i },
|
||||
'0x0'
|
||||
)
|
||||
);
|
||||
|
||||
console.log('extraLogic unlock + ', i);
|
||||
await unlock();
|
||||
|
||||
console.log('extraLogic return extraLogic2 + ', i);
|
||||
return extraLogic2(id, i);
|
||||
});
|
||||
13
packages/evm-provider.cm.ignore/src/onchain/extraLogic2.ts
Normal file
13
packages/evm-provider.cm.ignore/src/onchain/extraLogic2.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { cwait, readOp, TypedClaim } from 'cwait';
|
||||
|
||||
import { createWordKey, WordClaimBody } from '../offchain';
|
||||
|
||||
export const extraLogic2 = cwait(async (id: string, i: number) => {
|
||||
console.log('extraLogic2 START + ', i);
|
||||
|
||||
console.log('await extraLogic2 readOp + ', i);
|
||||
const result = await readOp<TypedClaim<WordClaimBody>>(createWordKey(id));
|
||||
|
||||
console.log('extraLogic2 END + ', i);
|
||||
return result;
|
||||
});
|
||||
1
packages/evm-provider.cm.ignore/src/onchain/index.ts
Normal file
1
packages/evm-provider.cm.ignore/src/onchain/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './contract';
|
||||
@ -0,0 +1,96 @@
|
||||
export enum Key {
|
||||
ACTIVE_INDEX = 'ACTIVE_INDEX',
|
||||
MAKER_INDEX = 'MAKER_INDEX',
|
||||
DATE_INDEX = 'DATE_INDEX',
|
||||
RATE_INDEX = 'RATE_INDEX',
|
||||
|
||||
MAKER = 'MAKER',
|
||||
|
||||
ORDER = 'ORDER', //ORDER_STATE + ORDER_FUNDS
|
||||
LATEST_ORDER_ID = 'LATEST_ORDER_ID', //INCREMENT_INDEX
|
||||
ORDER_DIRECTION_INDEX = 'ORDER_DIRECTION_INDEX',
|
||||
|
||||
PACT = 'PACT', //ORDER_STATE + ORDER_COLLATERAL
|
||||
LATEST_PACT_ID = 'LATEST_PACT_ID', //INCREMENT_INDEX
|
||||
PACT_PENALTY_INDEX = 'PACT_PENALTY_INDEX',
|
||||
|
||||
SWAP_INFO = 'SWAP_INFO', //L1_TX_INFO
|
||||
PAYMENT_NONCE = 'PAYMENT_NONCE', //BTC_NONCE
|
||||
UNIQUE_VALUE = 'UNIQUE_VALUE',
|
||||
FEE_POOL_ADDRESS = 'FEE_POOL_ADDRESS',
|
||||
}
|
||||
|
||||
export enum PUBLIC_METHODS {
|
||||
CREATE_ORDERS = 'CREATE_ORDERS',
|
||||
CANCEL_ORDERS = 'CANCEL_ORDERS',
|
||||
DEPOSIT_COLLATERAL = 'DEPOSIT_COLLATERAL',
|
||||
WITHDRAW_COLLATERAL = 'WITHDRAW_COLLATERAL',
|
||||
}
|
||||
|
||||
export const FEE: Record<`${PUBLIC_METHODS}` | 'CHANGE_FEE_POOL_ADDRESS', bigint> = {
|
||||
CREATE_ORDERS: 10000000n,
|
||||
CANCEL_ORDERS: 10000000n,
|
||||
DEPOSIT_COLLATERAL: 10000000n,
|
||||
WITHDRAW_COLLATERAL: 10000000n,
|
||||
CHANGE_FEE_POOL_ADDRESS: 10000000n,
|
||||
};
|
||||
|
||||
export enum ORDER_STATUS {
|
||||
ACTIVE = 'ACTIVE',
|
||||
DEACTIVATED = 'DEACTIVATED',
|
||||
DISABLED = 'DISABLED',
|
||||
}
|
||||
|
||||
export enum PACT_STATUS {
|
||||
ACTIVE = 'ACTIVE',
|
||||
DISABLED = 'DISABLED',
|
||||
}
|
||||
|
||||
export enum AddressEncoding {
|
||||
Hex = 'Hex',
|
||||
Base58 = 'Base58',
|
||||
Bech32 = 'Bech32',
|
||||
Bech32m = 'Bech32m',
|
||||
}
|
||||
|
||||
export enum ProviderType {
|
||||
Evm = 'Evm',
|
||||
Btc = 'Btc',
|
||||
}
|
||||
|
||||
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 = 'btc',
|
||||
tbtc = 'tbtc',
|
||||
}
|
||||
|
||||
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)[];
|
||||
3
packages/evm-provider.cm.ignore/src/shared/index.ts
Normal file
3
packages/evm-provider.cm.ignore/src/shared/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './keys';
|
||||
export * from './constants/constants';
|
||||
export * from './types';
|
||||
121
packages/evm-provider.cm.ignore/src/shared/types.ts
Normal file
121
packages/evm-provider.cm.ignore/src/shared/types.ts
Normal file
@ -0,0 +1,121 @@
|
||||
import type { HexString, User } from '@coinweb/contract-kit';
|
||||
import { HexBigInt } from 'lib/shared';
|
||||
|
||||
import { ORDER_STATUS, OrderBatchFields, AddressEncoding } from './constants/constants';
|
||||
|
||||
export type ProviderData = unknown;
|
||||
|
||||
export type BtcProviderData = {
|
||||
l1TxId: string;
|
||||
vout: number;
|
||||
psbt: string;
|
||||
};
|
||||
|
||||
export type DirectionParameter = {
|
||||
provider: string;
|
||||
providerData: ProviderData;
|
||||
value: HexBigInt;
|
||||
};
|
||||
|
||||
export type Direction = {
|
||||
from: DirectionParameter;
|
||||
to: DirectionParameter;
|
||||
};
|
||||
|
||||
export type OrderStateClaimBody = {
|
||||
recipient: string;
|
||||
cwebAmount: HexBigInt;
|
||||
minCwebSwapAmount: HexBigInt;
|
||||
directions: Direction[];
|
||||
createdAt: number;
|
||||
expirationDate: number;
|
||||
status: ORDER_STATUS;
|
||||
parentTxId: string;
|
||||
history: HistoryAccess;
|
||||
maker: User;
|
||||
};
|
||||
|
||||
export type SwapInfoData = {
|
||||
l1TxId: string;
|
||||
recipientAddress: string;
|
||||
backPayAddress: string;
|
||||
amount: HexBigInt;
|
||||
l2TxId: string;
|
||||
};
|
||||
|
||||
export type SwapToBtcL1Payload = {
|
||||
minL1Amount: HexBigInt;
|
||||
promisedL1Amount: HexBigInt;
|
||||
l1Recipient: HexString;
|
||||
fallbackRecipient: HexString;
|
||||
};
|
||||
|
||||
export type SwapToEvmL1Payload = {
|
||||
minL1Amount: HexBigInt;
|
||||
promisedL1Amount: HexBigInt;
|
||||
l1Recipient: HexString;
|
||||
};
|
||||
|
||||
export type SwapToEvmPreset = {
|
||||
toL1ChainType: L1Types.Evm;
|
||||
c2ContractId: HexString;
|
||||
c2ContractMethod: HexString;
|
||||
fallbackC1ContractId: HexString;
|
||||
fallbackC1ContractMethod: HexString;
|
||||
};
|
||||
|
||||
export type SwapToBtcPreset = {
|
||||
toL1ChainType: L1Types.Btc;
|
||||
c2ContractId: HexString;
|
||||
c2ContractMethod: HexString;
|
||||
encoding: AddressEncoding;
|
||||
};
|
||||
|
||||
export type SwapPreset = SwapToEvmPreset | SwapToBtcPreset;
|
||||
|
||||
export type CreateOrderBaseParams = {
|
||||
cwebAmount?: bigint;
|
||||
minCwebSwapAmount?: bigint;
|
||||
directions: Direction[];
|
||||
};
|
||||
|
||||
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 = {
|
||||
bech32: string;
|
||||
scriptHash: number;
|
||||
};
|
||||
10
packages/evm-provider.cm.ignore/tsconfig.build.json
Normal file
10
packages/evm-provider.cm.ignore/tsconfig.build.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": ["./src/**/*.ts"],
|
||||
"exclude": ["**/__tests__", "**/__mocks__", "*.tests.ts"]
|
||||
}
|
||||
9
packages/evm-provider.cm.ignore/tsconfig.dev.json
Normal file
9
packages/evm-provider.cm.ignore/tsconfig.dev.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"rootDir": "./src",
|
||||
"outDir": "./cweb_dist/"
|
||||
},
|
||||
"exclude": ["**/__tests__", "**/__mocks__", "vitest.config.ts", "tsconfig.dev.json", "*.tests.ts"]
|
||||
}
|
||||
13
packages/evm-provider.cm.ignore/tsconfig.json
Normal file
13
packages/evm-provider.cm.ignore/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"target": "ESNEXT",
|
||||
"module": "ESNEXT",
|
||||
"moduleResolution": "Bundler",
|
||||
"rootDir": ".",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"types": ["vitest/globals"]
|
||||
},
|
||||
"include": ["src/**/*.ts", "vitest.*.ts", "__tests__", "../cwap-cm-lib/src/onchain/features/logger.ts"]
|
||||
}
|
||||
14
packages/evm-provider.cm.ignore/vitest.config.ts
Normal file
14
packages/evm-provider.cm.ignore/vitest.config.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
reporters: 'default',
|
||||
silent: false,
|
||||
testTimeout: 240000,
|
||||
teardownTimeout: 240000,
|
||||
hookTimeout: 240000,
|
||||
pool: 'forks',
|
||||
},
|
||||
});
|
||||
106
packages/lib/src/shared/utils/claimKeys.ts
Normal file
106
packages/lib/src/shared/utils/claimKeys.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import { constructClaimKey } from '@coinweb/contract-kit';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type ClaimKeyFirstPartConstructor = (...args: any[]) => unknown[];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type ClaimKeySecondPartConstructor = (...args: any[]) => unknown[] | null;
|
||||
|
||||
type ClaimKeyConstructors = {
|
||||
firstPart?: ClaimKeyFirstPartConstructor;
|
||||
secondPart: ClaimKeySecondPartConstructor;
|
||||
};
|
||||
|
||||
type ClaimKey<TFirstPart extends unknown[], TSecondPart extends unknown[] | null> = {
|
||||
first_part: TFirstPart;
|
||||
second_part: TSecondPart;
|
||||
};
|
||||
|
||||
export type ClaimKeyDefinitions = {
|
||||
[Key: string]: ClaimKeyConstructors | ClaimKeyDefinitions;
|
||||
};
|
||||
|
||||
type KeyConstructor<
|
||||
TCreateSecondPart extends (...args: unknown[]) => unknown[] | null,
|
||||
TCreateFirstPart extends ((...args: unknown[]) => unknown[]) | undefined = undefined,
|
||||
> = {
|
||||
firstPart: TCreateFirstPart extends ClaimKeyFirstPartConstructor
|
||||
? (...args: Parameters<TCreateFirstPart>) => [string, ...ReturnType<TCreateFirstPart>]
|
||||
: () => [string];
|
||||
secondPart: TCreateSecondPart;
|
||||
} & (TCreateFirstPart extends ClaimKeySecondPartConstructor
|
||||
? (
|
||||
...args: [...Parameters<TCreateFirstPart>, ...Parameters<TCreateSecondPart>]
|
||||
) => ClaimKey<[string, ...ReturnType<TCreateFirstPart>], ReturnType<TCreateSecondPart>>
|
||||
: (...args: Parameters<TCreateSecondPart>) => ClaimKey<[string], ReturnType<TCreateSecondPart>>);
|
||||
|
||||
type ConstructKeys<T extends ClaimKeyDefinitions> = {
|
||||
[Key in keyof T]: T[Key] extends ClaimKeyDefinitions
|
||||
? ConstructKeys<T[Key]>
|
||||
: T[Key] extends ClaimKeyConstructors
|
||||
? KeyConstructor<T[Key]['secondPart'], T[Key]['firstPart']>
|
||||
: never;
|
||||
};
|
||||
|
||||
const domainPropSymbol = Symbol('domain');
|
||||
|
||||
export const constructClaimKeys = <T extends ClaimKeyDefinitions>(domain: string, keys: T): ConstructKeys<T> =>
|
||||
new Proxy(keys as ClaimKeyDefinitions & { [domainPropSymbol]?: string }, {
|
||||
get: (target, prop) => {
|
||||
if (typeof prop !== 'string') {
|
||||
throw new Error('Property is not a string');
|
||||
}
|
||||
|
||||
const value = target[prop];
|
||||
const currentDomain = target[domainPropSymbol] ? `${target[domainPropSymbol]}_${prop}` : domain;
|
||||
|
||||
if ('secondPart' in value) {
|
||||
const secondPart = value.secondPart;
|
||||
|
||||
const firstPartDefinedConstructor = value.firstPart;
|
||||
|
||||
if (typeof firstPartDefinedConstructor === 'function') {
|
||||
const firstPart = (...args: Parameters<typeof firstPartDefinedConstructor>) => [
|
||||
currentDomain,
|
||||
...firstPartDefinedConstructor(...args),
|
||||
];
|
||||
|
||||
return {
|
||||
firstPart,
|
||||
secondPart,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
firstPart: () => [currentDomain],
|
||||
secondPart,
|
||||
};
|
||||
}
|
||||
|
||||
(value as ClaimKeyDefinitions & { [domainPropSymbol]: string })[domainPropSymbol] = currentDomain;
|
||||
|
||||
return value;
|
||||
},
|
||||
apply(target, prop, argArray) {
|
||||
const value = target[prop];
|
||||
const currentDomain = target[domainPropSymbol] ? `${target[domainPropSymbol]}_${prop}` : domain;
|
||||
|
||||
const secondPartConstructor = value.secondPart;
|
||||
|
||||
if (typeof secondPartConstructor !== 'function') {
|
||||
throw new Error('Property is not callable');
|
||||
}
|
||||
|
||||
const secondPartArgs = argArray.slice(argArray.length - secondPartConstructor.length);
|
||||
const secondPart = secondPartConstructor(...secondPartArgs);
|
||||
|
||||
const firstPartDefinedConstructor = value.firstPart;
|
||||
|
||||
const firstPart: unknown[] = [currentDomain];
|
||||
|
||||
if (typeof firstPartDefinedConstructor === 'function') {
|
||||
firstPart.push(...firstPartDefinedConstructor(...argArray));
|
||||
}
|
||||
|
||||
return constructClaimKey(firstPart, secondPart);
|
||||
},
|
||||
}) as ConstructKeys<T>;
|
||||
@ -5,3 +5,4 @@ export * from './stableStringifyObject';
|
||||
export * from './toHex';
|
||||
export * from './toHex32';
|
||||
export * from './isEqualUser';
|
||||
export * from './claimKeys';
|
||||
|
||||
1
packages/market.cm/.gitignore
vendored
Normal file
1
packages/market.cm/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
deploy/calls.yaml
|
||||
12
packages/market.cm/deploy/calls.yaml.template
Normal file
12
packages/market.cm/deploy/calls.yaml.template
Normal file
@ -0,0 +1,12 @@
|
||||
# this is the contract id
|
||||
__CWEB_CONTRACT_SELF_REFERENCE__:
|
||||
# out contract does not take any arguments, so we pass an empty object
|
||||
args:
|
||||
- "CREATE_ORDER"
|
||||
- "0x000000000000000000000000000000000000000000000001236efcbcbb340000"
|
||||
- "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
|
||||
- "0x9A4250b8c30Ca3cC5Dc33Ddbe30f71509a2E60a5"
|
||||
- "0x00000000000000000000000000000000000000000000000002ea11e32ad50000"
|
||||
- "0x00000000000000000000000000000000000000000000000000000000000186a0"
|
||||
cweb_provided: "0x00000000000000000000000000000000000000000000000126590e9fe60a86a0"
|
||||
auth: true
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "contract.cm",
|
||||
"version": "0.0.1",
|
||||
"name": "market.cm",
|
||||
"version": "0.0.1-dev",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "yarn build:files && yarn pack:all",
|
||||
@ -24,7 +24,8 @@
|
||||
"@coinweb/self-register": "0.1.3",
|
||||
"@noble/hashes": "1.4.0",
|
||||
"bech32": "2.0.0",
|
||||
"bs58": "6.0.0"
|
||||
"bs58": "6.0.0",
|
||||
"lib": "workspaces:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.20.2"
|
||||
41
packages/market.cm/scripts/build.sh
Executable file
41
packages/market.cm/scripts/build.sh
Executable file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
ROOT=$DIR/..
|
||||
|
||||
rm -rf $ROOT/{cweb_dist/{on,off}chain,dist/tmp/{step{1,2,3},final}}
|
||||
mkdir -p $ROOT/{cweb_dist/{on,off}chain,dist/tmp/{step{1,2,3},final}}
|
||||
|
||||
(
|
||||
cd $ROOT
|
||||
cp -rf dist/offchain/. cweb_dist/offchain/
|
||||
|
||||
## Bundle and transpile `index.js` so it can be understood by the quickjs interpreter:
|
||||
echo 'import {cwebMain as f} from "../../../dist/onchain/index"; f();' \
|
||||
> dist/tmp/step1/onchain.js
|
||||
|
||||
yarn esbuild \
|
||||
--bundle \
|
||||
--log-level=error \
|
||||
--format=esm \
|
||||
dist/tmp/step1/onchain.js \
|
||||
--outfile=dist/tmp/step2/onchain.js
|
||||
|
||||
echo 'import * as std from "std";' |
|
||||
cat - dist/tmp/step2/onchain.js \
|
||||
> dist/tmp/step3/onchain.js
|
||||
|
||||
yarn esbuild \
|
||||
--bundle \
|
||||
--log-level=error \
|
||||
--format=esm \
|
||||
--external:std \
|
||||
--tree-shaking=true \
|
||||
dist/tmp/step3/onchain.js \
|
||||
--outfile=dist/tmp/final/onchain.js
|
||||
|
||||
cp dist/tmp/final/onchain.js cweb_dist/onchain/index.js
|
||||
)
|
||||
|
||||
rm -rf $ROOT/dist/{tmp,offchain,onchain}
|
||||
33
packages/market.cm/scripts/package-relink.js
Normal file
33
packages/market.cm/scripts/package-relink.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const workspaceLink = 'workspaces:*';
|
||||
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
// Update target package.json
|
||||
const targetPath = resolve(__dirname, '../dist/out/package.json');
|
||||
const targetPackage = JSON.parse(readFileSync(targetPath, 'utf8'));
|
||||
|
||||
// Process all cm- dependencies
|
||||
Object.keys(targetPackage.dependencies).forEach((dependency) => {
|
||||
if (dependency.startsWith('cwap-cm-')) {
|
||||
// Read source version from the corresponding package
|
||||
const sourcePath = resolve(__dirname, `../../${dependency}/package.json`);
|
||||
try {
|
||||
const sourcePackage = JSON.parse(readFileSync(sourcePath, 'utf8'));
|
||||
const sourceVersion = sourcePackage.version;
|
||||
|
||||
if (targetPackage.dependencies[dependency] === workspaceLink) {
|
||||
targetPackage.dependencies[dependency] = sourceVersion;
|
||||
} else {
|
||||
targetPackage.dependencies[dependency] = workspaceLink;
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`Warning: Could not read package.json for ${dependency} at ${sourcePath}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Write back the updated package.json
|
||||
writeFileSync(targetPath, JSON.stringify(targetPackage, null, 2));
|
||||
3
packages/market.cm/src/offchain/index.ts
Normal file
3
packages/market.cm/src/offchain/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './api';
|
||||
export * from './uiCommands';
|
||||
export * from '../shared';
|
||||
0
packages/market.cm/src/offchain/order/api/index.ts
Normal file
0
packages/market.cm/src/offchain/order/api/index.ts
Normal file
0
packages/market.cm/src/offchain/order/index.ts
Normal file
0
packages/market.cm/src/offchain/order/index.ts
Normal file
128
packages/market.cm/src/offchain/order/ui-commands/createOrder.ts
Normal file
128
packages/market.cm/src/offchain/order/ui-commands/createOrder.ts
Normal file
@ -0,0 +1,128 @@
|
||||
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');
|
||||
}
|
||||
|
||||
return constructUiCommand([
|
||||
constructCreateOrdersCall({
|
||||
contractId,
|
||||
orders: [
|
||||
[
|
||||
1,
|
||||
{
|
||||
baseAmount,
|
||||
l1Amount,
|
||||
minL1Amount,
|
||||
l1Address,
|
||||
chainData,
|
||||
},
|
||||
],
|
||||
],
|
||||
accessId,
|
||||
contractOwnerFee,
|
||||
}),
|
||||
]);
|
||||
};
|
||||
|
||||
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)]);
|
||||
};
|
||||
0
packages/market.cm/src/offchain/pact/api/index.ts
Normal file
0
packages/market.cm/src/offchain/pact/api/index.ts
Normal file
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user