Skip to content

Commit 9e38b93

Browse files
committed
feat: format returned tokenIn allowances and balances using tokenInDecimals
1 parent 99c0556 commit 9e38b93

File tree

7 files changed

+114
-47
lines changed

7 files changed

+114
-47
lines changed

.nx/version-plans/version-plan-1759906570919.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
ability-uniswap-swap: major
33
---
44

5-
Remove the ApproveAndSwap Ability Action from the Uniswap Swap Ability
5+
Remove the ApproveAndSwap Ability Action from the Uniswap Swap Ability, and format returned tokenIn allowances and balances as decimal strings

packages/apps/abilities-e2e/test-e2e/swap-no-native.spec.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ describe('Uniswap Swap Ability E2E Tests', () => {
344344
// Try to precheck with the malicious quote
345345
const precheckResult = await uniswapSwapAbilityClient.precheck(
346346
{
347-
action: AbilityAction.ApproveAndSwap,
347+
action: AbilityAction.Approve,
348348
rpcUrlForUniswap: RPC_URL,
349349
signedUniswapQuote: {
350350
quote: signedUniswapQuote.quote,
@@ -486,8 +486,17 @@ describe('Uniswap Swap Ability E2E Tests', () => {
486486
expect(precheckResult.result!.nativeTokenBalance).toBeUndefined();
487487
expect(precheckResult.result!.tokenInAddress).toBe(SWAP_TOKEN_IN_ADDRESS);
488488
expect(precheckResult.result!.tokenInBalance).toBeDefined();
489-
expect(BigInt(precheckResult.result!.tokenInBalance as string)).toBeGreaterThan(0n);
490-
expect(BigInt(precheckResult.result!.currentTokenInAllowanceForSpender)).toBeGreaterThan(0n);
489+
expect(
490+
ethers.utils
491+
.parseUnits(precheckResult.result!.tokenInBalance as string, SWAP_TOKEN_IN_DECIMALS)
492+
.toBigInt(),
493+
).toBeGreaterThan(0n);
494+
expect(precheckResult.result!.currentTokenInAllowanceForSpender as string).toBe(
495+
ethers.utils.formatUnits(
496+
ethers.utils.parseUnits(SWAP_AMOUNT.toString(), SWAP_TOKEN_IN_DECIMALS),
497+
SWAP_TOKEN_IN_DECIMALS,
498+
),
499+
);
491500
expect(precheckResult.result!.spenderAddress).toBe(signedUniswapQuote.quote.to);
492501
});
493502

packages/apps/abilities-e2e/test-e2e/swap.spec.ts

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,29 @@ import {
4646
const ALCHEMY_GAS_SPONSOR_API_KEY = getEnv('ALCHEMY_GAS_SPONSOR_API_KEY');
4747
const ALCHEMY_GAS_SPONSOR_POLICY_ID = getEnv('ALCHEMY_GAS_SPONSOR_POLICY_ID');
4848

49-
// const SWAP_AMOUNT = 80;
50-
// const SWAP_TOKEN_IN_ADDRESS = '0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed'; // DEGEN
51-
// const SWAP_TOKEN_IN_DECIMALS = 18;
49+
const SWAP_AMOUNT = 80;
50+
const SWAP_TOKEN_IN_ADDRESS = '0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed'; // DEGEN
51+
const SWAP_TOKEN_IN_DECIMALS = 18;
5252

5353
// const SWAP_AMOUNT = 0.0003;
5454
// const SWAP_TOKEN_IN_ADDRESS = '0x4200000000000000000000000000000000000006'; // WETH
5555
// const SWAP_TOKEN_IN_DECIMALS = 18;
5656

57-
const SWAP_AMOUNT = 0.1;
58-
const SWAP_TOKEN_IN_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; // USDC
59-
const SWAP_TOKEN_IN_DECIMALS = 6;
57+
// const SWAP_AMOUNT = 0.1;
58+
// const SWAP_TOKEN_IN_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; // USDC
59+
// const SWAP_TOKEN_IN_DECIMALS = 6;
60+
61+
const EXPECTED_SWAP_AMOUNT = ethers.utils.formatUnits(
62+
ethers.utils.parseUnits(SWAP_AMOUNT.toString(), SWAP_TOKEN_IN_DECIMALS),
63+
SWAP_TOKEN_IN_DECIMALS,
64+
);
6065

61-
// const SWAP_TOKEN_OUT_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; // USDC
62-
// const SWAP_TOKEN_OUT_DECIMALS = 6;
66+
const SWAP_TOKEN_OUT_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; // USDC
67+
const SWAP_TOKEN_OUT_DECIMALS = 6;
6368
// const SWAP_TOKEN_OUT_ADDRESS = '0x4200000000000000000000000000000000000006'; // WETH
6469
// const SWAP_TOKEN_OUT_DECIMALS = 18;
65-
const SWAP_TOKEN_OUT_ADDRESS = '0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed'; // DEGEN
66-
const SWAP_TOKEN_OUT_DECIMALS = 18;
70+
// const SWAP_TOKEN_OUT_ADDRESS = '0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed'; // DEGEN
71+
// const SWAP_TOKEN_OUT_DECIMALS = 18;
6772

6873
const RPC_URL = BASE_RPC_URL;
6974
const CHAIN_ID = 8453;
@@ -429,10 +434,8 @@ describe('Uniswap Swap Ability E2E Tests', () => {
429434
);
430435
expect(innerResult.spenderAddress).toBe(signedUniswapQuote.quote.to);
431436
expect(innerResult.tokenAddress).toBe(SWAP_TOKEN_IN_ADDRESS);
432-
expect(innerResult.requiredAllowance).toBe(
433-
ethers.utils.parseUnits(SWAP_AMOUNT.toString(), SWAP_TOKEN_IN_DECIMALS).toString(),
434-
);
435-
expect(innerResult.currentAllowance).toBe('0');
437+
expect(innerResult.requiredAllowance).toBe(EXPECTED_SWAP_AMOUNT);
438+
expect(innerResult.currentAllowance).toBe('0.0');
436439
});
437440

438441
it('should fail execute because of invalid ability action', async () => {
@@ -531,10 +534,8 @@ describe('Uniswap Swap Ability E2E Tests', () => {
531534

532535
expect(executeResult.result).toBeDefined();
533536
expect(executeResult.result.approvalTxHash).toBeUndefined();
534-
expect(executeResult.result.currentAllowance).toBeDefined();
535-
expect(BigInt(executeResult.result.currentAllowance!)).toBeGreaterThanOrEqual(
536-
BigInt(ethers.utils.parseUnits(SWAP_AMOUNT.toString(), SWAP_TOKEN_IN_DECIMALS).toString()),
537-
);
537+
expect(executeResult.result.currentAllowance!).toBe(EXPECTED_SWAP_AMOUNT);
538+
expect(executeResult.result.requiredAllowance!).toBe(EXPECTED_SWAP_AMOUNT);
538539
});
539540

540541
it('should successfully run precheck on the Uniswap Swap Ability', async () => {
@@ -581,12 +582,23 @@ describe('Uniswap Swap Ability E2E Tests', () => {
581582
// Verify the result is properly populated
582583
expect(precheckResult.result).toBeDefined();
583584
expect(precheckResult.result!.nativeTokenBalance).toBeDefined();
584-
expect(BigInt(precheckResult.result!.nativeTokenBalance as string)).toBeGreaterThan(0n);
585+
expect(
586+
ethers.utils.parseEther(precheckResult.result!.nativeTokenBalance as string).toBigInt(),
587+
).toBeGreaterThan(0n);
588+
585589
expect(precheckResult.result!.tokenInAddress).toBe(SWAP_TOKEN_IN_ADDRESS);
586590
expect(precheckResult.result!.tokenInBalance).toBeDefined();
587-
expect(BigInt(precheckResult.result!.tokenInBalance as string)).toBeGreaterThan(0n);
588-
expect(BigInt(precheckResult.result!.currentTokenInAllowanceForSpender)).toBeGreaterThan(0n);
591+
expect(
592+
ethers.utils
593+
.parseUnits(precheckResult.result!.tokenInBalance as string, SWAP_TOKEN_IN_DECIMALS)
594+
.toBigInt(),
595+
).toBeGreaterThan(0n);
596+
597+
expect(precheckResult.result!.currentTokenInAllowanceForSpender as string).toBe(
598+
EXPECTED_SWAP_AMOUNT,
599+
);
589600
expect(precheckResult.result!.spenderAddress).toBe(signedUniswapQuote.quote.to);
601+
expect(precheckResult.result!.requiredTokenInAllowance!).toBe(EXPECTED_SWAP_AMOUNT);
590602
});
591603

592604
it('should execute the Uniswap Swap Ability with the Agent Wallet PKP', async () => {
@@ -684,10 +696,8 @@ describe('Uniswap Swap Ability E2E Tests', () => {
684696
);
685697
expect(innerResult.spenderAddress).toBe(signedUniswapQuote.quote.to);
686698
expect(innerResult.tokenAddress).toBe(SWAP_TOKEN_IN_ADDRESS);
687-
expect(innerResult.requiredAllowance).toBe(
688-
ethers.utils.parseUnits(SWAP_AMOUNT.toString(), SWAP_TOKEN_IN_DECIMALS).toString(),
689-
);
690-
expect(innerResult.currentAllowance).toBe('0');
699+
expect(innerResult.requiredAllowance).toBe(EXPECTED_SWAP_AMOUNT);
700+
expect(innerResult.currentAllowance).toBe('0.0');
691701
});
692702

693703
it('should make a new ERC20 approval transaction for the Uniswap router', async () => {
@@ -769,10 +779,8 @@ describe('Uniswap Swap Ability E2E Tests', () => {
769779

770780
expect(executeResult.result).toBeDefined();
771781
expect(executeResult.result.approvalTxHash).toBeUndefined();
772-
expect(executeResult.result.currentAllowance).toBeDefined();
773-
expect(BigInt(executeResult.result.currentAllowance!)).toBeGreaterThanOrEqual(
774-
BigInt(ethers.utils.parseUnits(SWAP_AMOUNT.toString(), SWAP_TOKEN_IN_DECIMALS).toString()),
775-
);
782+
expect(executeResult.result.currentAllowance!).toBe(EXPECTED_SWAP_AMOUNT);
783+
expect(executeResult.result.requiredAllowance!).toBe(EXPECTED_SWAP_AMOUNT);
776784
});
777785

778786
it('should successfully run precheck on the Uniswap Swap Ability', async () => {
@@ -822,10 +830,16 @@ describe('Uniswap Swap Ability E2E Tests', () => {
822830
expect(precheckResult.result).toBeDefined();
823831
expect(precheckResult.result!.nativeTokenBalance).toBeUndefined();
824832
expect(precheckResult.result!.tokenInAddress).toBe(SWAP_TOKEN_IN_ADDRESS);
825-
expect(precheckResult.result!.tokenInBalance).toBeDefined();
826-
expect(BigInt(precheckResult.result!.tokenInBalance as string)).toBeGreaterThan(0n);
827-
expect(BigInt(precheckResult.result!.currentTokenInAllowanceForSpender)).toBeGreaterThan(0n);
833+
expect(
834+
ethers.utils
835+
.parseUnits(precheckResult.result!.tokenInBalance as string, SWAP_TOKEN_IN_DECIMALS)
836+
.toBigInt(),
837+
).toBeGreaterThan(0n);
838+
expect(precheckResult.result!.currentTokenInAllowanceForSpender as string).toBe(
839+
EXPECTED_SWAP_AMOUNT,
840+
);
828841
expect(precheckResult.result!.spenderAddress).toBe(signedUniswapQuote.quote.to);
842+
expect(precheckResult.result!.requiredTokenInAllowance!).toBe(EXPECTED_SWAP_AMOUNT);
829843
});
830844

831845
it('should execute the Uniswap Swap Ability with the Agent Wallet PKP', async () => {

packages/apps/ability-uniswap-swap/src/generated/lit-action.js

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"ipfsCid": "QmNhA92xLMq31iPfpK67Zdko9AMaHRs4JQShFdzGQ2fLUz"
2+
"ipfsCid": "QmNzpmybreenCN3TPQRp8VEKXAwV5LGNsTms5FcmPHZb4h"
33
}

packages/apps/ability-uniswap-swap/src/lib/schemas.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export const precheckSuccessSchema = z.object({
7272
.string()
7373
.describe('The current allowance of the input token used for the swap'),
7474
spenderAddress: z.string().describe('The Uniswap router address that will be used for the swap'),
75+
requiredTokenInAllowance: z
76+
.string()
77+
.describe('The required allowance of the input token for the swap for the ERC20 spender')
78+
.optional(),
7579
});
7680

7781
export const precheckFailSchema = z.object({
@@ -120,4 +124,8 @@ export const executeSuccessSchema = z.object({
120124
.string()
121125
.describe('The current allowance of the input token used for the swap for the ERC20 spender')
122126
.optional(),
127+
requiredAllowance: z
128+
.string()
129+
.describe('The required allowance of the input token used for the swap for the ERC20 spender')
130+
.optional(),
123131
});

packages/apps/ability-uniswap-swap/src/lib/vincent-ability.ts

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,14 @@ export const vincentAbility = createVincentAbility({
9191
if (action === AbilityAction.Approve) {
9292
return succeed({
9393
nativeTokenBalance: checkNativeTokenBalanceResultSuccess?.ethBalance.toString(),
94-
currentTokenInAllowanceForSpender: checkErc20AllowanceResult.currentAllowance.toString(),
94+
currentTokenInAllowanceForSpender: ethers.utils.formatUnits(
95+
checkErc20AllowanceResult.currentAllowance,
96+
quote.tokenInDecimals,
97+
),
98+
requiredTokenInAllowance: ethers.utils.formatUnits(
99+
checkErc20AllowanceResult.requiredAllowance,
100+
quote.tokenInDecimals,
101+
),
95102
spenderAddress: checkErc20AllowanceResult.spenderAddress,
96103
});
97104
}
@@ -103,8 +110,14 @@ export const vincentAbility = createVincentAbility({
103110
reason: checkErc20AllowanceResult.reason,
104111
spenderAddress: checkErc20AllowanceResult.spenderAddress,
105112
tokenAddress: checkErc20AllowanceResult.tokenAddress,
106-
requiredAllowance: checkErc20AllowanceResult.requiredAllowance.toString(),
107-
currentAllowance: checkErc20AllowanceResult.currentAllowance.toString(),
113+
requiredAllowance: ethers.utils.formatUnits(
114+
checkErc20AllowanceResult.requiredAllowance,
115+
quote.tokenInDecimals,
116+
),
117+
currentAllowance: ethers.utils.formatUnits(
118+
checkErc20AllowanceResult.currentAllowance,
119+
quote.tokenInDecimals,
120+
),
108121
});
109122
}
110123

@@ -120,8 +133,14 @@ export const vincentAbility = createVincentAbility({
120133
return fail({
121134
reason: checkErc20BalanceResult.reason,
122135
tokenAddress: checkErc20BalanceResult.tokenAddress,
123-
requiredTokenAmount: checkErc20BalanceResult.requiredTokenAmount.toString(),
124-
tokenBalance: checkErc20BalanceResult.tokenBalance.toString(),
136+
requiredTokenAmount: ethers.utils.formatUnits(
137+
checkErc20BalanceResult.requiredTokenAmount,
138+
quote.tokenInDecimals,
139+
),
140+
tokenBalance: ethers.utils.formatUnits(
141+
checkErc20BalanceResult.tokenBalance,
142+
quote.tokenInDecimals,
143+
),
125144
});
126145
}
127146

@@ -130,8 +149,18 @@ export const vincentAbility = createVincentAbility({
130149
return succeed({
131150
nativeTokenBalance: checkNativeTokenBalanceResultSuccess?.ethBalance.toString(),
132151
tokenInAddress: checkErc20BalanceResult.tokenAddress,
133-
tokenInBalance: checkErc20BalanceResult.tokenBalance.toString(),
134-
currentTokenInAllowanceForSpender: checkErc20AllowanceResult.currentAllowance.toString(),
152+
tokenInBalance: ethers.utils.formatUnits(
153+
checkErc20BalanceResult.tokenBalance,
154+
quote.tokenInDecimals,
155+
),
156+
currentTokenInAllowanceForSpender: ethers.utils.formatUnits(
157+
checkErc20AllowanceResult.currentAllowance,
158+
quote.tokenInDecimals,
159+
),
160+
requiredTokenInAllowance: ethers.utils.formatUnits(
161+
checkErc20AllowanceResult.requiredAllowance,
162+
quote.tokenInDecimals,
163+
),
135164
spenderAddress: checkErc20AllowanceResult.spenderAddress,
136165
});
137166
},
@@ -186,7 +215,14 @@ export const vincentAbility = createVincentAbility({
186215
// 1.1 Because the ability action is approve, we return success since the current allowance is sufficient,
187216
// and a new approval transaction is not needed.
188217
return succeed({
189-
currentAllowance: checkErc20AllowanceResult.currentAllowance.toString(),
218+
currentAllowance: ethers.utils.formatUnits(
219+
checkErc20AllowanceResult.currentAllowance,
220+
quote.tokenInDecimals,
221+
),
222+
requiredAllowance: ethers.utils.formatUnits(
223+
checkErc20AllowanceResult.requiredAllowance,
224+
quote.tokenInDecimals,
225+
),
190226
});
191227
} else {
192228
if (checkErc20AllowanceResult.reason.includes('insufficient ERC20 allowance for spender')) {

0 commit comments

Comments
 (0)