-
Notifications
You must be signed in to change notification settings - Fork 2
Add function and script that return IDs of open positions #289
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
Merged
illia-malachyn
merged 5 commits into
v0
from
illia-malachyn/add-get-position-ids-script
Mar 26, 2026
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
65bd300
Add function and script that return IDs of open positions
illia-malachyn 25b1ea3
add test for getPositionIDs function
illia-malachyn c96ff8e
remove unused arguments
illia-malachyn 97a876a
Apply suggestion from @nialexsan
nialexsan 2dd24d2
add get_positions_by_ids script
illia-malachyn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 |
|---|---|---|
| @@ -1,11 +1,11 @@ | ||
| // Returns the details of a specific position by its ID. | ||
| import "FlowALPv0" | ||
|
|
||
| access(all) fun main(poolAddress: Address, positionID: UInt64): FlowALPv0.PositionDetails { | ||
| let account = getAccount(poolAddress) | ||
| access(all) fun main(positionID: UInt64): FlowALPv0.PositionDetails { | ||
| let protocolAddress = Type<@FlowALPv0.Pool>().address! | ||
| let account = getAccount(protocolAddress) | ||
| let pool = account.capabilities.borrow<&FlowALPv0.Pool>(FlowALPv0.PoolPublicPath) | ||
| ?? panic("Could not find Pool at path \(FlowALPv0.PoolPublicPath)") | ||
|
|
||
| let poolRef = account.capabilities | ||
| .borrow<&FlowALPv0.Pool>(FlowALPv0.PoolPublicPath) | ||
| ?? panic("Could not borrow Pool reference from \(poolAddress)") | ||
|
|
||
| return poolRef.getPositionDetails(pid: positionID) | ||
| } | ||
| return pool.getPositionDetails(pid: positionID) | ||
| } |
This file contains hidden or 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,11 @@ | ||
| // Returns the IDs of all currently open positions in the pool. | ||
| import "FlowALPv0" | ||
|
|
||
| access(all) fun main(): [UInt64] { | ||
| let protocolAddress = Type<@FlowALPv0.Pool>().address! | ||
| let account = getAccount(protocolAddress) | ||
| let pool = account.capabilities.borrow<&FlowALPv0.Pool>(FlowALPv0.PoolPublicPath) | ||
| ?? panic("Could not find Pool at path \(FlowALPv0.PoolPublicPath)") | ||
|
|
||
| return pool.getPositionIDs() | ||
| } | ||
This file contains hidden or 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,15 @@ | ||
| // Returns the details of multiple positions by their IDs. | ||
| import "FlowALPv0" | ||
|
|
||
| access(all) fun main(positionIDs: [UInt64]): [FlowALPv0.PositionDetails] { | ||
| let protocolAddress = Type<@FlowALPv0.Pool>().address! | ||
| let account = getAccount(protocolAddress) | ||
| let pool = account.capabilities.borrow<&FlowALPv0.Pool>(FlowALPv0.PoolPublicPath) | ||
| ?? panic("Could not find Pool at path \(FlowALPv0.PoolPublicPath)") | ||
|
|
||
| let details: [FlowALPv0.PositionDetails] = [] | ||
| for id in positionIDs { | ||
| details.append(pool.getPositionDetails(pid: id)) | ||
| } | ||
| return details | ||
| } |
This file contains hidden or 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,99 @@ | ||
| import Test | ||
| import BlockchainHelpers | ||
|
|
||
| import "MOET" | ||
| import "FlowALPv0" | ||
| import "test_helpers.cdc" | ||
|
|
||
| // ----------------------------------------------------------------------------- | ||
| // getPositionIDs Test | ||
| // | ||
| // Verifies that Pool.getPositionIDs() correctly reflects opened and closed | ||
| // positions via the get_position_ids.cdc script. | ||
| // ----------------------------------------------------------------------------- | ||
|
|
||
| access(all) | ||
| fun setup() { | ||
| deployContracts() | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // Test: getPositionIDs tracks opens and closes correctly | ||
| // ============================================================================= | ||
| access(all) | ||
| fun test_getPositionIDs_lifecycle() { | ||
| // --- Setup --- | ||
| setMockOraclePrice(signer: PROTOCOL_ACCOUNT, forTokenIdentifier: FLOW_TOKEN_IDENTIFIER, price: 1.0) | ||
|
|
||
| createAndStorePool(signer: PROTOCOL_ACCOUNT, defaultTokenIdentifier: MOET_TOKEN_IDENTIFIER, beFailed: false) | ||
| addSupportedTokenZeroRateCurve( | ||
| signer: PROTOCOL_ACCOUNT, | ||
| tokenTypeIdentifier: FLOW_TOKEN_IDENTIFIER, | ||
| collateralFactor: 0.8, | ||
| borrowFactor: 1.0, | ||
| depositRate: 1_000_000.0, | ||
| depositCapacityCap: 1_000_000.0 | ||
| ) | ||
|
|
||
| let user = Test.createAccount() | ||
| setupMoetVault(user, beFailed: false) | ||
| mintFlow(to: user, amount: 10_000.0) | ||
|
|
||
| // --- No positions yet --- | ||
| var ids = getPositionIDs() | ||
| Test.assertEqual(0, ids.length) | ||
|
|
||
| // --- Open position 0 (with borrow) --- | ||
| createPosition(signer: user, amount: 100.0, vaultStoragePath: FLOW_VAULT_STORAGE_PATH, pushToDrawDownSink: true) | ||
|
|
||
| ids = getPositionIDs() | ||
| Test.assertEqual(1, ids.length) | ||
| Test.assert(ids.contains(UInt64(0)), message: "Expected position 0 in IDs") | ||
|
|
||
| // --- Open position 1 (with borrow) --- | ||
| createPosition(signer: user, amount: 100.0, vaultStoragePath: FLOW_VAULT_STORAGE_PATH, pushToDrawDownSink: true) | ||
|
|
||
| ids = getPositionIDs() | ||
| Test.assertEqual(2, ids.length) | ||
| Test.assert(ids.contains(UInt64(0)), message: "Expected position 0 in IDs") | ||
| Test.assert(ids.contains(UInt64(1)), message: "Expected position 1 in IDs") | ||
|
|
||
| // --- Open position 2 (no borrow, so closing won't need MOET repay) --- | ||
| createPosition(signer: user, amount: 100.0, vaultStoragePath: FLOW_VAULT_STORAGE_PATH, pushToDrawDownSink: false) | ||
|
|
||
| ids = getPositionIDs() | ||
| Test.assertEqual(3, ids.length) | ||
| Test.assert(ids.contains(UInt64(2)), message: "Expected position 2 in IDs") | ||
|
|
||
| // --- Close position 2 (no debt, straightforward) --- | ||
| closePosition(user: user, positionID: 2) | ||
|
|
||
| ids = getPositionIDs() | ||
| Test.assertEqual(2, ids.length) | ||
| Test.assert(!ids.contains(UInt64(2)), message: "Position 2 should be removed after close") | ||
| Test.assert(ids.contains(UInt64(0)), message: "Position 0 should still exist") | ||
| Test.assert(ids.contains(UInt64(1)), message: "Position 1 should still exist") | ||
|
|
||
| // --- Close position 0 (has debt, repay needed) --- | ||
| closePosition(user: user, positionID: 0) | ||
|
|
||
| ids = getPositionIDs() | ||
| Test.assertEqual(1, ids.length) | ||
| Test.assert(!ids.contains(UInt64(0)), message: "Position 0 should be removed after close") | ||
| Test.assert(ids.contains(UInt64(1)), message: "Position 1 should still exist") | ||
|
|
||
| // --- Open position 3 (new position after some closures) --- | ||
| createPosition(signer: user, amount: 100.0, vaultStoragePath: FLOW_VAULT_STORAGE_PATH, pushToDrawDownSink: true) | ||
|
|
||
| ids = getPositionIDs() | ||
| Test.assertEqual(2, ids.length) | ||
| Test.assert(ids.contains(UInt64(1)), message: "Position 1 should still exist") | ||
| Test.assert(ids.contains(UInt64(3)), message: "Expected position 3 in IDs") | ||
|
|
||
| // --- Close remaining positions --- | ||
| closePosition(user: user, positionID: 1) | ||
| closePosition(user: user, positionID: 3) | ||
|
|
||
| ids = getPositionIDs() | ||
| Test.assertEqual(0, ids.length) | ||
| } |
This file contains hidden or 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,68 @@ | ||
| import Test | ||
| import BlockchainHelpers | ||
|
|
||
| import "MOET" | ||
| import "FlowALPv0" | ||
| import "test_helpers.cdc" | ||
|
|
||
| // ----------------------------------------------------------------------------- | ||
| // getPositionsByIDs Test | ||
| // | ||
| // Verifies that the get_positions_by_ids.cdc script correctly returns position | ||
| // details for the requested IDs. | ||
| // ----------------------------------------------------------------------------- | ||
|
|
||
| access(all) | ||
| fun setup() { | ||
| deployContracts() | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // Test: getPositionsByIDs returns correct details for multiple positions | ||
| // ============================================================================= | ||
| access(all) | ||
| fun test_getPositionsByIDs() { | ||
| // --- Setup --- | ||
| setMockOraclePrice(signer: PROTOCOL_ACCOUNT, forTokenIdentifier: FLOW_TOKEN_IDENTIFIER, price: 1.0) | ||
|
|
||
| createAndStorePool(signer: PROTOCOL_ACCOUNT, defaultTokenIdentifier: MOET_TOKEN_IDENTIFIER, beFailed: false) | ||
| addSupportedTokenZeroRateCurve( | ||
| signer: PROTOCOL_ACCOUNT, | ||
| tokenTypeIdentifier: FLOW_TOKEN_IDENTIFIER, | ||
| collateralFactor: 0.8, | ||
| borrowFactor: 1.0, | ||
| depositRate: 1_000_000.0, | ||
| depositCapacityCap: 1_000_000.0 | ||
| ) | ||
|
|
||
| let user = Test.createAccount() | ||
| setupMoetVault(user, beFailed: false) | ||
| mintFlow(to: user, amount: 10_000.0) | ||
|
|
||
| // --- Open two positions --- | ||
| createPosition(signer: user, amount: 100.0, vaultStoragePath: FLOW_VAULT_STORAGE_PATH, pushToDrawDownSink: true) | ||
| createPosition(signer: user, amount: 200.0, vaultStoragePath: FLOW_VAULT_STORAGE_PATH, pushToDrawDownSink: false) | ||
|
|
||
| // --- Fetch both positions by IDs --- | ||
| let details = getPositionsByIDs(positionIDs: [UInt64(0), UInt64(1)]) | ||
| Test.assertEqual(2, details.length) | ||
|
|
||
| // Verify each result matches the single-position helper | ||
| let details0 = getPositionDetails(pid: 0, beFailed: false) | ||
| let details1 = getPositionDetails(pid: 1, beFailed: false) | ||
|
|
||
| Test.assertEqual(details0.health, details[0].health) | ||
| Test.assertEqual(details0.balances.length, details[0].balances.length) | ||
|
|
||
| Test.assertEqual(details1.health, details[1].health) | ||
| Test.assertEqual(details1.balances.length, details[1].balances.length) | ||
|
|
||
| // --- Empty input returns empty array --- | ||
| let emptyDetails = getPositionsByIDs(positionIDs: []) | ||
| Test.assertEqual(0, emptyDetails.length) | ||
|
|
||
| // --- Single ID works --- | ||
| let singleDetails = getPositionsByIDs(positionIDs: [UInt64(0)]) | ||
| Test.assertEqual(1, singleDetails.length) | ||
| Test.assertEqual(details0.health, singleDetails[0].health) | ||
| } |
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.