Skip to content

Commit

Permalink
Always approve allowance
Browse files Browse the repository at this point in the history
  • Loading branch information
mliu committed Dec 6, 2024
1 parent e248df2 commit 1d35c07
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 102 deletions.
13 changes: 9 additions & 4 deletions packages/examples/src/drawdownAndPayback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import {

const main = async () => {
const borrower = new StellarWallet(process.env.TEST_PRIVATE_KEY as string);
const poolName = POOL_NAME.Arf;
const network = StellarNetwork.humanet;
const poolName = POOL_NAME.Roam;
const network = StellarNetwork.testnet;

const availableBalanceForPool = await getAvailableBalanceForPool(
poolName,
Expand Down Expand Up @@ -54,7 +54,10 @@ const main = async () => {
network,
borrower
);
console.log("approveAllowance:", approveAllowance);
console.log(
"approveAllowance:",
approveAllowance.sendTransactionResponse?.hash
);

const drawdownResult = await drawdown(
poolName,
Expand All @@ -73,7 +76,9 @@ const main = async () => {
100_0000000 as any,
false
);
console.log(`Payment success. Tx hash: ${paymentResult}`);
console.log(
`Payment success. Tx hash: ${paymentResult.sendTransactionResponse?.hash}`
);
};

main();
14 changes: 5 additions & 9 deletions packages/sdk/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ associated with the given pool name on the current chain.</p></dd>
<dd><p>Draws down from a pool.</p></dd>
<dt><a href="#makePayment">makePayment(poolName, network, wallet, paymentAmount, principalOnly)</a> ⇒ <code>Promise.&lt;SentTransaction&gt;</code></dt>
<dd><p>Makes a payment.</p></dd>
<dt><a href="#approveSep41AllowanceIfInsufficient">approveSep41AllowanceIfInsufficient(poolName, network, wallet, spenderAddress, allowanceAmount)</a> ⇒ <code>Promise.&lt;(SentTransaction.&lt;null&gt;|null)&gt;</code></dt>
<dd><p>Approves an Sep41 allowance for a spender address, if the current allowance is insufficient.
<dt><a href="#approveSep41Allowance">approveSep41Allowance(poolName, network, wallet, spenderAddress)</a></dt>
<dd><p>Approves an Sep41 allowance for a spender address.
Allowance is required to do certain actions on the Huma protocol (e.g. makePayment for Autopay)</p></dd>
</dl>

Expand Down Expand Up @@ -130,22 +130,18 @@ associated with the given pool name on the current chain.</p>
| paymentAmount | <code>bigint</code> | <p>The amount to payback.</p> |
| principalOnly | <code>boolean</code> | <p>Whether this payment should ONLY apply to the principal</p> |

<a name="approveSep41AllowanceIfInsufficient"></a>
<a name="approveSep41Allowance"></a>

## approveSep41AllowanceIfInsufficient(poolName, network, wallet, spenderAddress, allowanceAmount) ⇒ <code>Promise.&lt;(SentTransaction.&lt;null&gt;\|null)&gt;</code>
<p>Approves an Sep41 allowance for a spender address, if the current allowance is insufficient.
## approveSep41Allowance(poolName, network, wallet, spenderAddress)
<p>Approves an Sep41 allowance for a spender address.
Allowance is required to do certain actions on the Huma protocol (e.g. makePayment for Autopay)</p>

**Kind**: global function
**Returns**: <code>Promise.&lt;(SentTransaction.&lt;null&gt;\|null)&gt;</code> - <ul>
<li>A Promise of the transaction response, or null if the allowance was already sufficient.</li>
</ul>

| Param | Type | Description |
| --- | --- | --- |
| poolName | <code>POOL\_NAME</code> | <p>The name of the credit pool to get the contract instance for.</p> |
| network | <code>StellarNetwork</code> | <p>The stellar network.</p> |
| wallet | <code>StellarWallet</code> | <p>The wallet used to send the transaction.</p> |
| spenderAddress | <code>string</code> | <p>The address of the spender to approve an allowance for.</p> |
| allowanceAmount | <code>bigint</code> | <p>The amount of tokens to approve, if applicable. Denominated in the Sep41 tokens.</p> |

20 changes: 4 additions & 16 deletions packages/sdk/src/helpers/CreditContractHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
StellarNetwork,
TransactionContext,
} from '../utils'
import { approveSep41AllowanceIfInsufficient } from './Sep41ContractHelper'
import { approveSep41Allowance } from './Sep41ContractHelper'

/**
* Returns the current pool balance available for borrowing
Expand Down Expand Up @@ -223,13 +223,7 @@ export async function approveAllowanceForSentinel(
method: 'get_sentinel',
})

const tx = await approveSep41AllowanceIfInsufficient(
poolName,
network,
wallet,
sentinel,
totalDue,
)
const tx = await approveSep41Allowance(poolName, network, wallet, sentinel)

return tx
}
Expand Down Expand Up @@ -311,13 +305,7 @@ export async function makePayment(
method: 'get_sentinel',
})

await approveSep41AllowanceIfInsufficient(
poolName,
network,
wallet,
sentinel,
paymentAmount,
)
await approveSep41Allowance(poolName, network, wallet, sentinel)

const poolCreditContext = new TransactionContext(
poolName,
Expand All @@ -344,7 +332,7 @@ export async function makePayment(
value: wallet.userInfo.publicKey,
})
}
const result: { result: readonly [bigint, boolean] } = await sendTransaction({
const result = await sendTransaction({
context: poolCreditContext,
method: principalOnly ? 'make_principal_payment' : 'make_payment',
params: params,
Expand Down
72 changes: 24 additions & 48 deletions packages/sdk/src/helpers/Sep41ContractHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '../utils'

/**
* Approves an Sep41 allowance for a spender address, if the current allowance is insufficient.
* Approves an Sep41 allowance for a spender address.
* Allowance is required to do certain actions on the Huma protocol (e.g. makePayment for Autopay)
*
* @async
Expand All @@ -18,15 +18,12 @@ import {
* @param {StellarNetwork} network - The stellar network.
* @param {StellarWallet} wallet - The wallet used to send the transaction.
* @param {string} spenderAddress - The address of the spender to approve an allowance for.
* @param {bigint} allowanceAmount - The amount of tokens to approve, if applicable. Denominated in the Sep41 tokens.
* @returns {Promise<SentTransaction<null> | null>} - A Promise of the transaction response, or null if the allowance was already sufficient.
*/
export async function approveSep41AllowanceIfInsufficient(
export async function approveSep41Allowance(
poolName: POOL_NAME,
network: StellarNetwork,
wallet: StellarWallet,
spenderAddress: string,
allowanceAmount: bigint,
) {
const underlyingTokenContext = new TransactionContext(
poolName,
Expand All @@ -35,9 +32,17 @@ export async function approveSep41AllowanceIfInsufficient(
'underlyingToken',
)

const { result: allowance }: { result: bigint } = await sendTransaction({
const { result: decimals }: { result: number } = await sendTransaction({
context: underlyingTokenContext,
method: 'decimals',
})
const latestLedger = await getLatestLedger(network)
// @TODO find a better to advance the ledger number
const advanceLedgerNum = 3_000_000

const result = await sendTransaction({
context: underlyingTokenContext,
method: 'allowance',
method: 'approve',
params: [
{
name: 'from',
Expand All @@ -49,48 +54,19 @@ export async function approveSep41AllowanceIfInsufficient(
type: ScValType.address,
value: spenderAddress,
},
{
name: 'amount',
type: ScValType.i128,
value: 1000_000_000 * Math.pow(10, Number(decimals)),
},
{
name: 'expiration_ledger',
type: ScValType.u32,
value: latestLedger.sequence + advanceLedgerNum,
},
],
shouldSignTransaction: true,
})
const { result: decimals }: { result: number } = await sendTransaction({
context: underlyingTokenContext,
method: 'decimals',
})

if (allowance < allowanceAmount) {
const latestLedger = await getLatestLedger(network)
// @TODO find a better to advance the ledger number
const advanceLedgerNum = 3_000_000

const result = await sendTransaction({
context: underlyingTokenContext,
method: 'approve',
params: [
{
name: 'from',
type: ScValType.address,
value: wallet.userInfo.publicKey,
},
{
name: 'spender',
type: ScValType.address,
value: spenderAddress,
},
{
name: 'amount',
type: ScValType.i128,
value: 1000_000_000 * Math.pow(10, Number(decimals)),
},
{
name: 'expiration_ledger',
type: ScValType.u32,
value: latestLedger.sequence + advanceLedgerNum,
},
],
shouldSignTransaction: true,
})

return result
}

return null
return result
}
29 changes: 4 additions & 25 deletions packages/sdk/tests/helpers/Sep41ContractHelper.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { approveSep41AllowanceIfInsufficient } from '../../src/helpers/Sep41ContractHelper'
import { approveSep41Allowance } from '../../src/helpers/Sep41ContractHelper'
import { StellarWallet } from '../../src/services'
import {
getLatestLedger,
Expand All @@ -22,35 +22,15 @@ jest.mock('../../src/utils/common', () => ({
getLatestLedger: jest.fn(),
}))

describe('approveSep41AllowanceIfInsufficient', () => {
describe('approveSep41Allowance', () => {
const mockPoolName = POOL_NAME.Arf
const mockNetwork = StellarNetwork.mainnet
const mockWallet = new StellarWallet(
'SB2EYCOYEITOLL5NTD5ADVHFLZWPMQCMAZ33R4FP5GS3KLG3TA63WKPO',
)
const mockSpenderAddress = 'spender123'
const mockAllowanceAmount = 1000n

it('should return null if the current allowance is sufficient', async () => {
;(sendTransaction as jest.Mock)
.mockResolvedValueOnce({
result: 2000n,
})
.mockResolvedValueOnce({
result: 2,
})

const result = await approveSep41AllowanceIfInsufficient(
mockPoolName,
mockNetwork,
mockWallet,
mockSpenderAddress,
mockAllowanceAmount,
)
expect(result).toBeNull()
})

it('should return a transaction result if the current allowance is insufficient', async () => {
it('should return a transaction result', async () => {
;(sendTransaction as jest.Mock)
.mockResolvedValueOnce({
result: 500n,
Expand All @@ -65,12 +45,11 @@ describe('approveSep41AllowanceIfInsufficient', () => {
const mockLatestLedger = { sequence: 123456 }
;(getLatestLedger as jest.Mock).mockResolvedValue(mockLatestLedger)

const result = await approveSep41AllowanceIfInsufficient(
const result = await approveSep41Allowance(
mockPoolName,
mockNetwork,
mockWallet,
mockSpenderAddress,
mockAllowanceAmount,
)
expect(result).toEqual({ result: 'transactionResult' })
})
Expand Down

0 comments on commit 1d35c07

Please sign in to comment.