Skip to content

Commit

Permalink
fix dex v2 worker
Browse files Browse the repository at this point in the history
  • Loading branch information
m1n999999 committed Nov 26, 2024
1 parent 8185861 commit 276f91d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 47 deletions.
3 changes: 0 additions & 3 deletions examples/dex-v2-worker-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Network } from "@minswap/lucid-cardano";

import { BlockfrostAdapter, NetworkId } from "../src";
import { DexV2Worker } from "../src/dex-v2-worker";
import { NetworkEnvironment } from "../src/types/network";
import { getBackendLucidInstance } from "../src/utils/lucid";

async function main(): Promise<void> {
Expand All @@ -29,8 +28,6 @@ async function main(): Promise<void> {
);

const worker = new DexV2Worker({
networkEnv: NetworkEnvironment.TESTNET_PREPROD,
networkId: NetworkId.TESTNET,
lucid,
blockfrostAdapter,
privateKey:
Expand Down
73 changes: 34 additions & 39 deletions src/dex-v2-worker.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
import { Lucid } from "@minswap/lucid-cardano";
import { Data, Lucid } from "@minswap/lucid-cardano";

import { BlockfrostAdapter, DexV2, DexV2Constant, OrderV2 } from ".";
import { NetworkEnvironment, NetworkId } from "./types/network";
import { runRecurringJob } from "./utils/job";

type DexV2WorkerConstructor = {
networkEnv: NetworkEnvironment;
networkId: NetworkId;
lucid: Lucid;
blockfrostAdapter: BlockfrostAdapter;
privateKey: string;
};

export class DexV2Worker {
private readonly networkEnv: NetworkEnvironment;
private readonly networkId: NetworkId;
private readonly lucid: Lucid;
private readonly blockfrostAdapter: BlockfrostAdapter;
private readonly privateKey: string;

constructor({
networkEnv,
networkId,
lucid,
blockfrostAdapter,
privateKey,
}: DexV2WorkerConstructor) {
this.networkEnv = networkEnv;
this.networkId = networkId;
this.lucid = lucid;
this.blockfrostAdapter = blockfrostAdapter;
this.privateKey = privateKey;
Expand All @@ -42,11 +33,10 @@ export class DexV2Worker {
}

async runWorker(): Promise<void> {
console.info("start run dex v2 worker");
const { orders: allOrders } = await this.blockfrostAdapter.getAllV2Orders();
const currentSlot = await this.blockfrostAdapter.currentSlot();
const currentTime = this.lucid.utils.slotToUnixTime(currentSlot);
const expiredOrders: OrderV2.State[] = [];
const mapDatum: Record<string, string> = {};
for (const order of allOrders) {
const orderDatum = order.datum;
const expiredOptions = orderDatum.expiredOptions;
Expand All @@ -62,46 +52,51 @@ export class DexV2Worker {
continue;
}

const mapDatum: Record<string, string> = {};
const receiverDatum = orderDatum.refundReceiverDatum;
let rawDatum: string | undefined = undefined;
if (receiverDatum.type === OrderV2.ExtraDatumType.INLINE_DATUM) {
let rawDatum: string | undefined = undefined;
try {
rawDatum = await this.blockfrostAdapter.getDatumByDatumHash(
receiverDatum.hash
);
mapDatum[receiverDatum.hash] = rawDatum;
// eslint-disable-next-line unused-imports/no-unused-vars
} catch (_err) {
continue;
}
mapDatum[receiverDatum.hash] = rawDatum;
}
expiredOrders.push(order);
if (expiredOrders.length === 20) {
break;
}
}
if (expiredOrders.length > 0) {
const orderUtxos = await this.lucid.utxosByOutRef(
expiredOrders.map((state) => ({
txHash: state.txIn.txHash,
outputIndex: state.txIn.index,
}))
);
const txComplete = await new DexV2(
this.lucid,
this.blockfrostAdapter
).cancelExpiredOrders({
orderUtxos: orderUtxos,
currentSlot,
extraDatumMap: mapDatum,
});

const signedTx = await txComplete
.signWithPrivateKey(this.privateKey)
.complete();
const orderUtxos = await this.lucid.utxosByOutRef([
{
txHash: order.txIn.txHash,
outputIndex: order.txIn.index,
},
]);
if (orderUtxos.length === 0) {
continue;
}
try {
orderUtxos[0].datum = Data.to(OrderV2.Datum.toPlutusData(orderDatum));
const txComplete = await new DexV2(
this.lucid,
this.blockfrostAdapter
).cancelExpiredOrders({
orderUtxos: orderUtxos,
currentSlot,
extraDatumMap: mapDatum,
});
const signedTx = await txComplete
.signWithPrivateKey(this.privateKey)
.complete();

const txId = await signedTx.submit();
console.info(`Transaction submitted successfully: ${txId}`);
const txId = await signedTx.submit();
console.info(`Transaction submitted successfully: ${txId}`);
break;
} catch (err) {
console.error(err);
continue;
}
}
}
}
56 changes: 51 additions & 5 deletions src/types/order.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Address, Constr, Data } from "@minswap/lucid-cardano";
import invariant from "@minswap/tiny-invariant";

import { AddressPlutusData } from "./address.internal";
import { Asset } from "./asset";
Expand Down Expand Up @@ -479,6 +480,11 @@ export namespace OrderV2 {
export namespace AuthorizationMethod {
export function fromPlutusData(data: Constr<Data>): AuthorizationMethod {
let type: AuthorizationMethodType;
if (data.fields.length !== 1) {
throw Error(
`Field length of AuthorizationMethod must be in 1, actual: ${data.fields.length}`
);
}
switch (data.index) {
case AuthorizationMethodType.SIGNATURE: {
type = AuthorizationMethodType.SIGNATURE;
Expand Down Expand Up @@ -1091,17 +1097,29 @@ export namespace OrderV2 {
export function fromPlutusData(data: Constr<Data>): ExtraDatum {
switch (data.index) {
case ExtraDatumType.NO_DATUM: {
invariant(
data.fields.length === 0,
`Field Length of ExtraDatum.NO_DATUM must be 0, actually ${data.fields.length}`
);
return {
type: ExtraDatumType.NO_DATUM,
};
}
case ExtraDatumType.DATUM_HASH: {
invariant(
data.fields.length === 1,
`Field Length of ExtraDatum.DATUM_HASH must be 1, actually ${data.fields.length}`
);
return {
type: ExtraDatumType.DATUM_HASH,
hash: data.fields[0] as string,
};
}
case ExtraDatumType.INLINE_DATUM: {
invariant(
data.fields.length === 1,
`Field Length of ExtraDatum.INLINE_DATUM must be 1, actually ${data.fields.length}`
);
return {
type: ExtraDatumType.INLINE_DATUM,
hash: data.fields[0] as string,
Expand Down Expand Up @@ -1152,20 +1170,46 @@ export namespace OrderV2 {
`Index of Order Datum must be 0, actual: ${data.index}`
);
}
if (data.fields.length !== 9) {
throw new Error(
`Fields Length of Order Datum must be 9, actual: ${data.index}`
);
}
const maybeExpiry = data.fields[8] as Constr<Data>;
let expiry: bigint[] | undefined;
switch (maybeExpiry.index) {
case 0: {
expiry = maybeExpiry.fields as bigint[];
if (expiry.length !== 2) {
if (maybeExpiry.fields.length !== 1) {
throw new Error(
`Order Expiry list must have 2 elements, actual: ${expiry.length}`
`Order maybeExpiry length must have 1 field, actual: ${maybeExpiry.fields.length}`
);
}
const expiryOptions = maybeExpiry.fields[0] as Constr<Data>;
switch (expiryOptions.index) {
case 0: {
expiry = expiryOptions.fields as bigint[];
if (expiry.length !== 2) {
throw new Error(
`Order Expiry list must have 2 elements, actual: ${expiry.length}`
);
}
break;
}
default: {
throw new Error(
`Index of Expiry Options must have 1, actual: ${expiryOptions.index}`
);
}
}
break;
}
case 1: {
expiry = undefined;
if (maybeExpiry.fields.length === 0) {
throw new Error(
`Order undefined Expiry must have 0 elements, actual: ${maybeExpiry.fields.length}`
);
}
break;
}
default: {
Expand Down Expand Up @@ -1216,8 +1260,10 @@ export namespace OrderV2 {
datum.maxBatcherFee,
datum.expiredOptions
? new Constr(0, [
datum.expiredOptions.expiredTime,
datum.expiredOptions.maxCancellationTip,
new Constr(0, [
datum.expiredOptions.expiredTime,
datum.expiredOptions.maxCancellationTip,
]),
])
: new Constr(1, []),
]);
Expand Down

0 comments on commit 276f91d

Please sign in to comment.