Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
50 changes: 50 additions & 0 deletions apps/indexer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Petra Vault uses the No-Code Indexing (NCI) service from [Geomi](https://geomi.d

- [Setup Instructions](#setup-instructions)
- [Environment Configuration](#environment-configuration)
- [Initial-owner Discovery on Mainnet](#initial-owner-discovery-on-mainnet)

## Setup Instructions

Expand Down Expand Up @@ -63,3 +64,52 @@ NEXT_PUBLIC_MULTISIG_INDEXER_TESTNET_ENDPOINT="https://api.testnet.aptoslabs.com
| `NEXT_PUBLIC_MULTISIG_INDEXER_MAINNET_ENDPOINT` | GraphQL endpoint for mainnet | `https://api.mainnet.aptoslabs.com/nocode/v1/api/[id]/v1/graphql` |
| `NEXT_PUBLIC_MULTISIG_INDEXER_TESTNET_API_KEY` | API key for testnet processor | `AG-...` |
| `NEXT_PUBLIC_MULTISIG_INDEXER_TESTNET_ENDPOINT` | GraphQL endpoint for testnet | `https://api.testnet.aptoslabs.com/nocode/v1/api/[id]/v1/graphql` |

## Initial-owner Discovery on Mainnet

`multisig-mainnet.yaml` adds `multisig_creation_candidates` alongside the existing
transaction and owner-activity tables. It maps argument `0` of
`0x1::multisig_account::create_with_owners` into a nullable `owners` address array.
The YAML uses the full framework address because Geomi's editor otherwise drops
the payload mapping during its function ABI lookup.

The mapping was tested in `multisig-creation-probe-v2` with Mainnet creation
versions `7345859301` and `7350673760`. Both were returned for the invited owner
once indexing reached their versions. The production table uses the same mappings
under the name `multisig_creation_candidates`.

After deploying, indexing the required history, and exposing the new table to the
mobile API key, query candidate versions for the active wallet:

```graphql
query VaultCreationCandidates(
$owner: String!
$afterVersion: bigint! = "0"
$limit: Int! = 100
) {
multisig_creation_candidates(
where: { owners: { _contains: [$owner] }, version: { _gt: $afterVersion } }
order_by: { version: asc }
limit: $limit
) {
version
owners
}
}
```

For each subsequent page, use the last returned version as `afterVersion` until
the result is empty. Mobile integration is still required: merge these versions
with existing creator-history and owner-event discovery, resolve successful
transactions into vault addresses, deduplicate them, and verify current ownership.
The query returns creation candidates, not vault addresses or current membership.
Argument `0` contains additional owners only; it excludes the creator and does
not cover other creation functions or custom wrappers.

**Deployment remains a separate step.** The processor needs `FeeStatement` events
to create rows before payload enrichment. This stores a row for every matching
fee event, including unrelated transactions with null owners and failed creation
calls. Filtering the GraphQL query does not reduce ingestion. Plan ingestion cost
and backfill before deployment; the YAML's `starting_version: 0` requests history
from genesis. The promoted config has been checked locally, but has not been
deployed or verified using the mobile API key.
103 changes: 90 additions & 13 deletions apps/indexer/multisig-mainnet.yaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
spec_identifier:
spec_creator: shepherd@aptoslabs.com
spec_name: remapping-processor
spec_version: 0.0.10
spec_version: "0.0.21"
common_config:
network: mainnet
starting_version: 0
starting_version_override: null
custom_config:
transaction_metadata:
timestamp: []
timestamp:
- table: multisig_transactions
column: timestamp
version:
- table: multisig_transactions
column: version
- table: multisig_owner_activities
column: version
- table: multisig_creation_candidates
column: version
epoch: []
block_height: []
hash: []
events:
# Payload mappings enrich event-created rows; they do not filter ingestion.
0x1::transaction_fee::FeeStatement:
event_fields:
$.total_charge_gas_units:
- table: multisig_creation_candidates
column: total_charge_gas_units
event_metadata:
sequence_number: []
creation_number: []
account_address: []
event_type:
- table: multisig_creation_candidates
column: fee_event_type
event_index: []
constant_values: []
0x1::multisig_account::AddOwners:
event_fields:
$.multisig_account:
Expand Down Expand Up @@ -263,11 +283,16 @@ custom_config:
column: event_type
event_index: []
constant_values: []
payload: {}
payload:
# Geomi's function ABI lookup requires the full address.
0x0000000000000000000000000000000000000000000000000000000000000001::multisig_account::create_with_owners:
'0':
- table: multisig_creation_candidates
column: owners
db_schema:
multisig_transactions:
version:
is_index: false
is_index: true
is_nullable: false
is_option: false
is_primary_key: false
Expand All @@ -276,6 +301,16 @@ custom_config:
column_type:
type: transaction_metadata
column_type: version
timestamp:
is_index: false
is_nullable: false
is_option: false
is_primary_key: false
is_vec: false
default_value: null
column_type:
type: transaction_metadata
column_type: timestamp
executor:
is_index: false
is_nullable: false
Expand All @@ -287,15 +322,15 @@ custom_config:
type: move_type
column_type: address
multisig_account:
is_index: false
is_index: true
is_nullable: false
is_option: false
is_primary_key: true
is_vec: false
default_value: null
column_type:
type: event_metadata
column_type: account_address
type: move_type
column_type: address
num_rejections:
is_index: false
is_nullable: true
Expand Down Expand Up @@ -348,7 +383,7 @@ custom_config:
column_type: string
multisig_owner_activities:
version:
is_index: false
is_index: true
is_nullable: false
is_option: false
is_primary_key: true
Expand All @@ -365,10 +400,10 @@ custom_config:
is_vec: false
default_value: null
column_type:
type: event_metadata
column_type: account_address
type: move_type
column_type: address
owners_added:
is_index: false
is_index: true
is_nullable: true
is_option: false
is_primary_key: false
Expand All @@ -388,7 +423,7 @@ custom_config:
type: event_metadata
column_type: event_type
owners_removed:
is_index: false
is_index: true
is_nullable: true
is_option: false
is_primary_key: false
Expand All @@ -398,7 +433,7 @@ custom_config:
type: move_type
column_type: address
owner_vote:
is_index: false
is_index: true
is_nullable: true
is_option: false
is_primary_key: false
Expand All @@ -407,3 +442,45 @@ custom_config:
column_type:
type: move_type
column_type: address
multisig_creation_candidates:
version:
is_index: true
is_nullable: false
is_option: false
is_primary_key: true
is_vec: false
default_value: null
column_type:
type: transaction_metadata
column_type: version
fee_event_type:
is_index: false
is_nullable: false
is_option: false
is_primary_key: false
is_vec: false
default_value: null
column_type:
type: event_metadata
column_type: event_type
total_charge_gas_units:
is_index: false
is_nullable: false
is_option: false
is_primary_key: false
is_vec: false
default_value: null
column_type:
type: move_type
column_type: u64
owners:
is_index: true
# Unrelated fee rows have no matching payload argument.
is_nullable: true
is_option: false
is_primary_key: false
is_vec: true
default_value: null
column_type:
type: move_type
column_type: address
25 changes: 19 additions & 6 deletions apps/indexer/multisig-testnet.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
spec_identifier:
spec_creator: shepherd@aptoslabs.com
spec_name: remapping-processor
spec_version: 0.0.10
spec_version: "0.0.21"
common_config:
network: testnet
starting_version: 4500665800
starting_version_override: null
custom_config:
transaction_metadata:
timestamp: []
timestamp:
- table: multisig_transactions
column: timestamp
version:
- table: multisig_transactions
column: version
- table: multisig_owner_activities
column: version
epoch: []
block_height: []
hash: []
events:
0x1::multisig_account::AddOwners:
event_fields:
Expand Down Expand Up @@ -276,6 +279,16 @@ custom_config:
column_type:
type: transaction_metadata
column_type: version
timestamp:
is_index: false
is_nullable: false
is_option: false
is_primary_key: false
is_vec: false
default_value: null
column_type:
type: transaction_metadata
column_type: timestamp
executor:
is_index: false
is_nullable: false
Expand All @@ -294,8 +307,8 @@ custom_config:
is_vec: false
default_value: null
column_type:
type: event_metadata
column_type: account_address
type: move_type
column_type: address
num_rejections:
is_index: false
is_nullable: true
Expand Down Expand Up @@ -365,8 +378,8 @@ custom_config:
is_vec: false
default_value: null
column_type:
type: event_metadata
column_type: account_address
type: move_type
column_type: address
owners_added:
is_index: false
is_nullable: true
Expand Down
14 changes: 0 additions & 14 deletions apps/web/actions/fetchCachedTransaction.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,17 @@ export default function VaultTransactionsPage() {
if (!executionEvents) return undefined;

// Sort transactions by timestamp in descending order (newest first)
const sortedEvents = executionEvents.pages.flat().sort((a, b) => {
const timestampA = a.transaction?.timestamp
? Number(a.transaction.timestamp) / 1000
: 0;
const timestampB = b.transaction?.timestamp
? Number(b.transaction.timestamp) / 1000
: 0;
return timestampB - timestampA;
});
const sortedEvents = executionEvents.pages
.flatMap((page) => page.events)
.sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));

// Group by month
const groupedByMonth: Record<string, ExecutionEvent[]> = {};

sortedEvents.forEach((event) => {
if (!event.transaction?.timestamp) return;
if (!event.timestamp) return;
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated

const date = new Date(
Math.floor(Number(event.transaction.timestamp) / 1000)
);
const date = new Date(event.timestamp);
const monthYear = `${date.toLocaleString('default', { month: 'long' })} ${date.getFullYear()}`;

if (!groupedByMonth[monthYear]) {
Expand Down Expand Up @@ -153,7 +145,6 @@ export default function VaultTransactionsPage() {
}}
>
<TransactionRow
transaction={event.transaction}
executionEvent={event}
network={network}
/>
Expand Down
Loading
Loading