Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions packages/token-app/app/api/wallet/etf/mint-recipe/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { NextRequest, NextResponse } from "next/server";
import {
getWrappedSdkForParty,
getWrappedSdkWithKeyPairForParty,
keyPairFromSeed,
getSdkForParty,
mintRecipeTemplateId,
ActiveContractResponse,
} from "@denotecapital/token-sdk";

interface MintRecipeParams {
issuer: string;
instrumentId: string;
authorizedMinters: string[];
composition: string;
}

export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams;
const issuer = searchParams.get("issuer");

if (!issuer) {
return NextResponse.json(
{ error: "Missing issuer" },
{ status: 400 }
);
}

const sdk = await getSdkForParty(issuer);
const ledger = sdk.userLedger!;
const end = await ledger.ledgerEnd();

const activeContracts = (await ledger.activeContracts({
offset: end.offset,
filterByParty: true,
parties: [issuer],
templateIds: [mintRecipeTemplateId],
})) as ActiveContractResponse<MintRecipeParams>[];

const recipes = activeContracts.map((contract) => {
const jsActive = contract.contractEntry.JsActiveContract;
if (!jsActive) return null;

const createArg = jsActive.createdEvent.createArgument;
const contractId = jsActive.createdEvent.contractId;

return {
contractId,
issuer: createArg.issuer,
instrumentId: createArg.instrumentId,
authorizedMinters: createArg.authorizedMinters,
composition: createArg.composition,
};
});

const validRecipes = recipes.filter((recipe) => recipe !== null);

return NextResponse.json({ recipes: validRecipes });
} catch (error) {
console.error("Error getting mint recipes:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Unknown error" },
{ status: 500 }
);
}
}

export async function POST(request: NextRequest) {
try {
const { issuer, instrumentId, authorizedMinters, composition, seed } =
await request.json();

if (
!issuer ||
!instrumentId ||
!authorizedMinters ||
!composition ||
!seed
) {
return NextResponse.json(
{ error: "Missing required parameters" },
{ status: 400 }
);
}

if (
!Array.isArray(authorizedMinters) ||
authorizedMinters.length === 0
) {
return NextResponse.json(
{ error: "authorizedMinters must be a non-empty array" },
{ status: 400 }
);
}

const keyPair = keyPairFromSeed(seed);
const wrappedSdk = await getWrappedSdkWithKeyPairForParty(
issuer,
keyPair
);

await wrappedSdk.etf.mintRecipe.create({
issuer,
instrumentId,
authorizedMinters,
composition,
});

return NextResponse.json({ success: true });
} catch (error) {
console.error("Error creating mint recipe:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Unknown error" },
{ status: 500 }
);
}
}
34 changes: 34 additions & 0 deletions packages/token-app/app/api/wallet/etf/mint-request/accept/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { NextRequest, NextResponse } from "next/server";
import {
getWrappedSdkWithKeyPairForParty,
keyPairFromSeed,
} from "@denotecapital/token-sdk";

export async function POST(request: NextRequest) {
try {
const { contractId, issuer, seed } = await request.json();

if (!contractId || !issuer || !seed) {
return NextResponse.json(
{ error: "Missing required parameters" },
{ status: 400 }
);
}

const keyPair = keyPairFromSeed(seed);
const wrappedSdk = await getWrappedSdkWithKeyPairForParty(
issuer,
keyPair
);

await wrappedSdk.etf.mintRequest.accept(contractId);

return NextResponse.json({ success: true });
} catch (error) {
console.error("Error accepting ETF mint request:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Unknown error" },
{ status: 500 }
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { NextRequest, NextResponse } from "next/server";
import {
getWrappedSdkWithKeyPairForParty,
keyPairFromSeed,
} from "@denotecapital/token-sdk";

export async function POST(request: NextRequest) {
try {
const { contractId, issuer, seed } = await request.json();

if (!contractId || !issuer || !seed) {
return NextResponse.json(
{ error: "Missing required parameters" },
{ status: 400 }
);
}

const keyPair = keyPairFromSeed(seed);
const wrappedSdk = await getWrappedSdkWithKeyPairForParty(
issuer,
keyPair
);

await wrappedSdk.etf.mintRequest.decline(contractId);

return NextResponse.json({ success: true });
} catch (error) {
console.error("Error declining ETF mint request:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Unknown error" },
{ status: 500 }
);
}
}
145 changes: 145 additions & 0 deletions packages/token-app/app/api/wallet/etf/mint-request/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { NextRequest, NextResponse } from "next/server";
import {
getWrappedSdkForParty,
getWrappedSdkWithKeyPairForParty,
keyPairFromSeed,
getSdkForParty,
etfMintRequestTemplateId,
ActiveContractResponse,
} from "@denotecapital/token-sdk";

interface EtfMintRequestParams {
mintRecipeCid: string;
requester: string;
amount: number;
transferInstructionCids: string[];
issuer: string;
}

export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams;
const partyId = searchParams.get("partyId");
const issuer = searchParams.get("issuer");

if (!partyId || !issuer) {
return NextResponse.json(
{ error: "Missing partyId or issuer" },
{ status: 400 }
);
}

const wrappedSdk = await getWrappedSdkForParty(partyId);
const contractIds = await wrappedSdk.etf.mintRequest.getAll(issuer);

const sdk = await getSdkForParty(partyId);
const ledger = sdk.userLedger!;
const end = await ledger.ledgerEnd();

const activeContracts = (await ledger.activeContracts({
offset: end.offset,
filterByParty: true,
parties: [partyId],
templateIds: [etfMintRequestTemplateId],
})) as ActiveContractResponse<EtfMintRequestParams>[];

const requests = contractIds.map((contractId: string) => {
const contract = activeContracts.find(
(c) =>
c.contractEntry.JsActiveContract?.createdEvent
.contractId === contractId
);
if (!contract?.contractEntry.JsActiveContract) {
return null;
}

const jsActive = contract.contractEntry.JsActiveContract;
const createArg = jsActive.createdEvent.createArgument;

return {
contractId,
mintRecipeCid: createArg.mintRecipeCid,
requester: createArg.requester,
amount: createArg.amount,
transferInstructionCids: createArg.transferInstructionCids,
issuer: createArg.issuer,
};
});

const validRequests = requests.filter((req) => req !== null);

return NextResponse.json({ requests: validRequests });
} catch (error) {
console.error("Error getting ETF mint requests:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Unknown error" },
{ status: 500 }
);
}
}

export async function POST(request: NextRequest) {
try {
const {
mintRecipeCid,
requester,
amount,
transferInstructionCids,
issuer,
seed,
} = await request.json();

if (
!mintRecipeCid ||
!requester ||
!amount ||
!transferInstructionCids ||
!issuer ||
!seed
) {
return NextResponse.json(
{ error: "Missing required parameters" },
{ status: 400 }
);
}

if (
!Array.isArray(transferInstructionCids) ||
transferInstructionCids.length === 0
) {
return NextResponse.json(
{ error: "transferInstructionCids must be a non-empty array" },
{ status: 400 }
);
}

if (typeof amount !== "number" || amount <= 0) {
return NextResponse.json(
{ error: "amount must be a positive number" },
{ status: 400 }
);
}

const keyPair = keyPairFromSeed(seed);
const wrappedSdk = await getWrappedSdkWithKeyPairForParty(
requester,
keyPair
);

await wrappedSdk.etf.mintRequest.create({
mintRecipeCid,
requester,
amount,
transferInstructionCids,
issuer,
});

return NextResponse.json({ success: true });
} catch (error) {
console.error("Error creating ETF mint request:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Unknown error" },
{ status: 500 }
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { NextRequest, NextResponse } from "next/server";
import {
getWrappedSdkWithKeyPairForParty,
keyPairFromSeed,
} from "@denotecapital/token-sdk";

export async function POST(request: NextRequest) {
try {
const { contractId, requester, seed } = await request.json();

if (!contractId || !requester || !seed) {
return NextResponse.json(
{ error: "Missing required parameters" },
{ status: 400 }
);
}

const keyPair = keyPairFromSeed(seed);
const wrappedSdk = await getWrappedSdkWithKeyPairForParty(
requester,
keyPair
);

await wrappedSdk.etf.mintRequest.withdraw(contractId);

return NextResponse.json({ success: true });
} catch (error) {
console.error("Error withdrawing ETF mint request:", error);
return NextResponse.json(
{ error: error instanceof Error ? error.message : "Unknown error" },
{ status: 500 }
);
}
}
Loading
Loading