Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

anchor: api integ test swap with quote response #129

Merged
merged 1 commit into from
Jun 13, 2024
Merged
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
5 changes: 4 additions & 1 deletion anchor/src/client/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ export class BaseClient {
} else {
const defaultProvider = anchor.AnchorProvider.env();
const url = defaultProvider.connection.rpcEndpoint;
const connection = new Connection(url, "confirmed");
const connection = new Connection(url, {
commitment: "confirmed",
confirmTransactionInitialTimeout: 45000 // default timeout is 30s, we extend it to 45s
});
this.provider = new anchor.AnchorProvider(
connection,
defaultProvider.wallet,
Expand Down
51 changes: 49 additions & 2 deletions anchor/tests/glam_api_tx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe("glam_api_tx", () => {
}
}, 30_000);

it("Jupiter swap", async () => {
it("Jupiter swap with quote params", async () => {
const response = await fetch(`${API}/tx/jupiter/swap`, {
method: "POST",
headers: { "Content-Type": "application/json" },
Expand Down Expand Up @@ -109,7 +109,54 @@ describe("glam_api_tx", () => {
console.error("Error", error);
throw error;
}
}, 30_000);
}, 60_000);

it("Jupiter swap with quote response", async () => {
const quoteParams: any = {
inputMint: msol.toBase58(),
outputMint: wsol.toBase58(),
amount: 50000000,
autoSlippage: true,
autoSlippageCollisionUsdValue: 1000,
swapMode: "ExactIn",
onlyDirectRoutes: false,
asLegacyTransaction: false,
maxAccounts: 20
};
const quoteResponse = await (
await fetch(
`${glamClient.jupiterApi}/quote?${new URLSearchParams(
Object.entries(quoteParams)
)}`
)
).json();

console.log("quoteResponse", quoteResponse);

const response = await fetch(`${API}/tx/jupiter/swap`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
fund,
manager,
quoteResponse
})
});

const { tx } = await response.json();
console.log("tx", tx);

const vTx = VersionedTransaction.deserialize(Buffer.from(tx, "hex"));
try {
const txId = await (
glamClient.provider as anchor.AnchorProvider
).sendAndConfirm(vTx, [glamClient.getWalletSigner()], confirmOptions);
console.log("jupiter swap txId", txId);
} catch (error) {
console.error("Error", error);
throw error;
}
}, 60_000);

it("Stake 0.1 sol", async () => {
const response = await fetch(`${API}/tx/marinade/stake`, {
Expand Down
63 changes: 35 additions & 28 deletions api/src/routers/tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,6 @@ import { Router } from "express";
import { validatePubkey, validateBN } from "../validation";
import { Transaction, VersionedTransaction } from "@solana/web3.js";

/*
* Jupiter
*/

const jupiterSwapTx = async (client, req, res) => {
const fund = validatePubkey(req.body.fund);
const manager = validatePubkey(req.body.manager);

if (!fund || !manager) {
return res.sendStatus(400);
}

try {
const tx = await client.jupiter.swapTx(
fund,
manager,
req.body.quote,
req.body.quoteResponse,
req.body.swapInstruction
);
return serializeVersionedTx(tx, res);
} catch (err) {
console.log(err);
return res.status(400).send({ error: err.message });
}
};

/*
* Marinade
*/
Expand Down Expand Up @@ -119,7 +92,41 @@ const router = Router();

router.post("/tx/jupiter/swap", async (req, res) => {
res.set("content-type", "application/json");
return jupiterSwapTx(req.client, req, res);

const fund = validatePubkey(req.body.fund);
const manager = validatePubkey(req.body.manager);

if (!fund || !manager) {
return res.status(400).send({ error: "Invalid fund or manager" });
}

const { quote, quoteResponse, swapInstruction, addressLookupTableAddresses } =
req.body;

if (!quote && !quoteResponse) {
// If quote and quoteResponse are not provided, swapInstruction and addressLookupTableAddresses must be provided
if (!swapInstruction || !addressLookupTableAddresses) {
return res.status(400).send({
error:
"Both swapInstruction and addressLookupTableAddresses must be provided"
});
}
}

try {
const tx = await req.client.jupiter.swapTx(
fund,
manager,
quote,
quoteResponse,
swapInstruction,
addressLookupTableAddresses
);
return serializeVersionedTx(tx, res);
} catch (err) {
console.log(err);
return res.status(400).send({ error: err.message });
}
});

router.post("/tx/marinade/stake", async (req, res) => {
Expand Down
28 changes: 28 additions & 0 deletions api/tests/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,31 @@ describe("Test /prices", () => {
});
});
});

describe("Test /tx/jupiter/swap", () => {
afterAll(() => {
server.close();
});

it("Invalid manager/fund params", async () => {
const res = await requestWithSupertest.post("/tx/jupiter/swap").send({
fund: "xyz",
manager: "abc"
});
expect(res.status).toEqual(400);
expect(res.body).toEqual({ error: "Invalid fund or manager" });
});

it("Invalid swap params", async () => {
const res = await requestWithSupertest.post("/tx/jupiter/swap").send({
fund: "11111111111111111111111111111111",
manager: "11111111111111111111111111111111",
swapInstruction: "abc"
});
expect(res.status).toEqual(400);
expect(res.body).toEqual({
error:
"Both swapInstruction and addressLookupTableAddresses must be provided"
});
});
});