-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: jupiter tests, fix: swap tests
- Loading branch information
1 parent
08e84b3
commit b66fd25
Showing
5 changed files
with
252 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { NetworkNames } from "@enkryptcom/types"; | ||
import { PublicKey } from "@solana/web3.js"; | ||
import { toBN } from "web3-utils"; | ||
import { NetworkType, TokenType, TokenTypeTo } from "../../../src/types"; | ||
|
||
export const nodeURL = "https://nodes.mewapi.io/rpc/sol"; | ||
|
||
export const amount = toBN("100000"); | ||
|
||
export const fromAddress = "CMGoYEKM8kSXwN9HzYiwRiZRXoMtEAQ98ZiPE9y67T38"; | ||
export const toAddress = "3zDT4WonZsGr6x6ysQeuhTHtabpdawZNsjhC6g1yZDEK"; | ||
|
||
export const fromTokenNative: TokenType = { | ||
address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", | ||
decimals: 9, | ||
logoURI: "", | ||
name: "Solana", | ||
symbol: "SOL", | ||
rank: 1, | ||
cgId: "solana", | ||
type: NetworkType.Solana, | ||
}; | ||
|
||
/** @see https://solscan.io/token/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v */ | ||
export const fromToken: TokenType = { | ||
address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", | ||
decimals: 6, | ||
logoURI: | ||
"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/logo.png", | ||
name: "USDC", | ||
symbol: "USDC", | ||
rank: 5, | ||
cgId: "usd-coin", | ||
type: NetworkType.Solana, | ||
}; | ||
|
||
/** @see https://solscan.io/token/So11111111111111111111111111111111111111112 */ | ||
export const toTokenWSOL: TokenTypeTo = { | ||
address: "So11111111111111111111111111111111111111112", | ||
decimals: 9, | ||
logoURI: | ||
"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png", | ||
name: "Wrapped SOL", | ||
symbol: "WSOL", | ||
rank: 15, | ||
cgId: "wrapped-solana", | ||
type: NetworkType.EVM, | ||
networkInfo: { | ||
name: NetworkNames.Solana, | ||
isAddress: (address: string) => { | ||
try { | ||
// eslint-disable-next-line no-new | ||
new PublicKey(address); | ||
return Promise.resolve(true); | ||
} catch (err) { | ||
return Promise.resolve(false); | ||
} | ||
}, | ||
}, | ||
}; | ||
|
||
/** @see https://solscan.io/token/Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB */ | ||
export const toToken: TokenTypeTo = { | ||
address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", | ||
decimals: 6, | ||
logoURI: | ||
"https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB/logo.svg", | ||
name: "Tether", | ||
symbol: "USDT", | ||
rank: 10, | ||
cgId: "tether", | ||
type: NetworkType.Solana, | ||
networkInfo: { | ||
name: NetworkNames.Solana, | ||
isAddress: (address: string) => { | ||
try { | ||
// eslint-disable-next-line no-new | ||
new PublicKey(address); | ||
return Promise.resolve(true); | ||
} catch (err) { | ||
return Promise.resolve(false); | ||
} | ||
}, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import { | ||
AddressLookupTableAccount, | ||
ComputeBudgetInstruction, | ||
ComputeBudgetProgram, | ||
Connection, | ||
TransactionMessage, | ||
VersionedTransaction, | ||
} from "@solana/web3.js"; | ||
import { expect } from "chai"; | ||
import { Jupiter } from "../src/providers/jupiter"; | ||
import { | ||
ProviderName, | ||
ProviderQuoteResponse, | ||
ProviderSwapResponse, | ||
SolanaTransaction, | ||
SupportedNetworkName, | ||
WalletIdentifier, | ||
} from "../src/types"; | ||
import { | ||
fromToken, | ||
amount, | ||
fromAddress, | ||
toAddress, | ||
nodeURL, | ||
toToken, | ||
} from "./fixtures/solana/configs"; | ||
|
||
describe("Jupiter Provider", () => { | ||
const conn = new Connection(nodeURL); | ||
const jupiter = new Jupiter(conn, SupportedNetworkName.Solana); | ||
|
||
// // TODO: | ||
// it("Should generate a swap transaction that creates both the source referral fee Associated Token Account and the destination Associated Token Account account if it doesn't exist", async () => { | ||
// // | ||
// }) | ||
// | ||
// // TODO: | ||
// it("Should generate a swap transaction that creates the destination Associated Token Account if it doesn't exist", async () => { | ||
// // | ||
// }) | ||
// | ||
// // TODO: | ||
// it("Should generate a swap transaction that creates the source referral fee Associated Token Account if it doesn't exist", async () => { | ||
// // | ||
// }) | ||
// | ||
// // TODO: | ||
// it("Should generate a swap transaction that creates both the source referral fee Associated Token Account if it doesn't exist", async () => { | ||
// // | ||
// }) | ||
|
||
it("Should return a quote", async () => { | ||
const quote: null | ProviderQuoteResponse = await jupiter.getQuote( | ||
{ | ||
amount, | ||
fromAddress, | ||
fromToken, | ||
toToken, | ||
toAddress, | ||
}, | ||
{ infiniteApproval: true, walletIdentifier: WalletIdentifier.enkrypt } | ||
); | ||
expect(quote!.provider).to.be.eq(ProviderName.jupiter); | ||
expect(quote!.quote.meta.infiniteApproval).to.be.eq(true); | ||
expect(quote!.quote.meta.walletIdentifier).to.be.eq( | ||
WalletIdentifier.enkrypt | ||
); | ||
expect(quote!.fromTokenAmount.toString()).to.be.eq(amount.toString()); | ||
expect(quote!.toTokenAmount.gtn(0)).to.be.eq(true); | ||
|
||
const swap: ProviderSwapResponse = await jupiter.getSwap(quote!.quote); | ||
expect(swap.transactions.length).to.be.eq(1); | ||
|
||
const tx = VersionedTransaction.deserialize( | ||
Buffer.from( | ||
(swap.transactions[0] as SolanaTransaction).serialized, | ||
"base64" | ||
) | ||
); | ||
|
||
// Decode the transaction and check some facts about it | ||
|
||
// Get lookup addresses (addresses optimized out of the transaction) | ||
const addressLookupTableAccounts: AddressLookupTableAccount[] = []; | ||
for (let i = 0, len = tx.message.addressTableLookups.length; i < len; i++) { | ||
const addressTableLookup = tx.message.addressTableLookups[i]; | ||
const result = await conn.getAddressLookupTable( | ||
addressTableLookup.accountKey | ||
); | ||
const addressLookupTableAccount = result.value; | ||
// eslint-disable-next-line no-unused-expressions | ||
expect( | ||
addressLookupTableAccount, | ||
"Address lookup table account not found" | ||
).to.be.ok; | ||
addressLookupTableAccounts.push(addressLookupTableAccount!); | ||
} | ||
// Decode message | ||
const decompiledMessage = TransactionMessage.decompile(tx.message, { | ||
addressLookupTableAccounts, | ||
}); | ||
|
||
// Decode instructions | ||
let computeBudget: undefined | number; | ||
let priorityRate: undefined | number | bigint; | ||
for (let i = 0, len = decompiledMessage.instructions.length; i < len; i++) { | ||
const instruction = decompiledMessage.instructions[i]; | ||
switch (instruction.programId.toBase58()) { | ||
case ComputeBudgetProgram.programId.toBase58(): { | ||
const instructionType = | ||
ComputeBudgetInstruction.decodeInstructionType(instruction); | ||
switch (instructionType) { | ||
case "SetComputeUnitLimit": { | ||
// eslint-disable-next-line no-unused-expressions | ||
expect( | ||
computeBudget == null, | ||
"Multiple SetComputeUnitLimit instructions found in the same transaction" | ||
).to.be.ok; | ||
const command = | ||
ComputeBudgetInstruction.decodeSetComputeUnitLimit(instruction); | ||
computeBudget = command.units; | ||
break; | ||
} | ||
case "SetComputeUnitPrice": { | ||
// eslint-disable-next-line no-unused-expressions | ||
expect( | ||
priorityRate == null, | ||
"Multiple SetComputeUnitPrice instructions found in the same transaction" | ||
).to.be.ok; | ||
const command = | ||
ComputeBudgetInstruction.decodeSetComputeUnitPrice(instruction); | ||
priorityRate = command.microLamports; | ||
break; | ||
} | ||
default: /* noop */ | ||
} | ||
break; | ||
} | ||
default: /* noop */ | ||
} | ||
} | ||
|
||
expect( | ||
decompiledMessage.payerKey.toBase58(), | ||
"Payer key is not the from address" | ||
).to.equal(fromAddress); | ||
}).timeout(10_000); | ||
}); |