Skip to content
This repository was archived by the owner on Feb 8, 2025. It is now read-only.

Z 295 policy events #256

Merged
merged 22 commits into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b2a0389
refactor(api): generated approve/rejection proposal insert queries
hbriese Jun 25, 2024
97aef48
refactor(api): shorten core import paths
hbriese Jun 25, 2024
ac35825
feat(api): deduplicated subscriptions
hbriese Jun 26, 2024
89ef6b5
perf(api): optimize transaction execution flow
hbriese Jun 26, 2024
93f6f1c
perf(api): optimize transaction proposal
hbriese Jun 26, 2024
b39063f
feat(api): remove loading indicator from send quick action
hbriese Jun 26, 2024
0a91cea
perf(api): improve PolicyState latest tracking
hbriese Jun 26, 2024
ad2bccd
perf(api): refetch balance when invalidating
hbriese Jun 27, 2024
9d84271
feat(api): policyUpdated subscription
hbriese Jun 27, 2024
a2fe4f7
feat(app): subscribe to policy updates
hbriese Jun 27, 2024
298a280
test(api): remove now unnecessary linking tests
hbriese Jun 27, 2024
1e5db1d
feat(api): field level instrumentation
hbriese Jun 27, 2024
18ad86c
feat(api): better account updated subscription
hbriese Jun 28, 2024
62e227a
feat(app): globally subscribe to account, policy, proposal and transf…
hbriese Jun 28, 2024
c234ec1
fix(api): proposing transaction with value
hbriese Jun 28, 2024
c06b8c8
perf(api): reduce sentry sampling rates
hbriese Jun 28, 2024
1534a92
test(api): expose redis port for api tests
hbriese Jun 28, 2024
d6e6744
fix(api): increase lock and stalled duration to prevent jobs stalling…
hbriese Jun 29, 2024
9ab12d0
fix(api): approving and rejecting proposal with existing response
hbriese Jun 30, 2024
2584b9e
feat(api): execute policy transactions when it's executed
hbriese Jun 30, 2024
eb46968
feat(app): cache query data when invalidated
hbriese Jun 30, 2024
0d46162
feat(api): try execute transaction when it is meaningfully updated
hbriese Jun 30, 2024
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
2 changes: 2 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ jobs:
services:
redis:
image: redis
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion api/dbschema/default.esdl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module default {
upgradedAtBlock: bigint { constraint min_value(0); }
photo: Url;
required property active := exists .upgradedAtBlock;
multi policies: Policy { on source delete delete target; on target delete allow; }
multi link policies := (select .<account[is Policy] filter .isLatest);
multi link proposals := .<account[is Proposal];
multi link transactions := .<account[is Transaction];
multi link messages := .<account[is Message];
Expand Down
8 changes: 4 additions & 4 deletions api/dbschema/edgeql-js/__spec__.ts

Large diffs are not rendered by default.

77 changes: 39 additions & 38 deletions api/dbschema/edgeql-js/modules/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ export type $AccountλShape = $.typeutil.flatten<Omit<$LabelledλShape, "address
"implementation": $.PropertyDesc<$Address, $.Cardinality.One, false, false, false, false>;
"photo": $.PropertyDesc<$Url, $.Cardinality.AtMostOne, false, false, false, false>;
"salt": $.PropertyDesc<$Bytes32, $.Cardinality.One, false, false, false, false>;
"policies": $.LinkDesc<$Policy, $.Cardinality.Many, {}, false, false, false, false>;
"approvers": $.LinkDesc<$Approver, $.Cardinality.Many, {}, false, true, false, false>;
"messages": $.LinkDesc<$Message, $.Cardinality.Many, {}, false, true, false, false>;
"proposals": $.LinkDesc<$Proposal, $.Cardinality.Many, {}, false, true, false, false>;
"transactions": $.LinkDesc<$Transaction, $.Cardinality.Many, {}, false, true, false, false>;
"transfers": $.LinkDesc<$Transfer, $.Cardinality.Many, {}, false, true, false, false>;
"policies": $.LinkDesc<$Policy, $.Cardinality.Many, {}, false, true, false, false>;
"approvers": $.LinkDesc<$Approver, $.Cardinality.Many, {}, false, true, false, false>;
"<account[is Proposal]": $.LinkDesc<$Proposal, $.Cardinality.Many, {}, false, false, false, false>;
"<account[is Message]": $.LinkDesc<$Message, $.Cardinality.Many, {}, false, false, false, false>;
"<account[is Transaction]": $.LinkDesc<$Transaction, $.Cardinality.Many, {}, false, false, false, false>;
Expand Down Expand Up @@ -437,12 +437,17 @@ export type $PolicyStateλShape = $.typeutil.flatten<_std.$Object_8ce8c71ee4fa5f
"proposal": $.LinkDesc<$Transaction, $.Cardinality.AtMostOne, {}, false, false, false, false>;
"initState": $.PropertyDesc<_std.$bool, $.Cardinality.One, false, true, false, false>;
"isDraft": $.PropertyDesc<_std.$bool, $.Cardinality.One, false, true, false, false>;
"latest": $.LinkDesc<$Policy, $.Cardinality.AtMostOne, {}, false, true, false, false>;
"latest": $.LinkDesc<$PolicyState, $.Cardinality.AtMostOne, {}, false, true, false, false>;
"isActive": $.PropertyDesc<_std.$bool, $.Cardinality.One, false, true, false, false>;
"isLatest": $.PropertyDesc<_std.$bool, $.Cardinality.One, false, false, false, true>;
"<draft[is PolicyState]": $.LinkDesc<$PolicyState, $.Cardinality.Many, {}, false, false, false, false>;
"<draft[is Policy]": $.LinkDesc<$Policy, $.Cardinality.Many, {}, false, false, false, false>;
"<draft[is RemovedPolicy]": $.LinkDesc<$RemovedPolicy, $.Cardinality.Many, {}, false, false, false, false>;
"<latest[is RemovedPolicy]": $.LinkDesc<$RemovedPolicy, $.Cardinality.Many, {}, false, false, false, false>;
"<latest[is Policy]": $.LinkDesc<$Policy, $.Cardinality.Many, {}, false, false, false, false>;
"<latest[is PolicyState]": $.LinkDesc<$PolicyState, $.Cardinality.Many, {}, false, false, false, false>;
"<draft": $.LinkDesc<$.ObjectType, $.Cardinality.Many, {}, false, false, false, false>;
"<latest": $.LinkDesc<$.ObjectType, $.Cardinality.Many, {}, false, false, false, false>;
}>;
type $PolicyState = $.ObjectType<"default::PolicyState", $PolicyStateλShape, null, [
..._std.$Object_8ce8c71ee4fa5f73840c22d7eaa58588['__exclusives__'],
Expand All @@ -461,15 +466,11 @@ export type $PolicyλShape = $.typeutil.flatten<$PolicyStateλShape & {
"threshold": $.PropertyDesc<$uint16, $.Cardinality.One, false, false, false, false>;
"<policy[is Message]": $.LinkDesc<$Message, $.Cardinality.Many, {}, false, false, false, false>;
"<policy[is Transaction]": $.LinkDesc<$Transaction, $.Cardinality.Many, {}, false, false, false, false>;
"<policies[is Account]": $.LinkDesc<$Account, $.Cardinality.Many, {}, false, false, false, false>;
"<spentBy[is Transfer]": $.LinkDesc<$Transfer, $.Cardinality.Many, {}, false, false, false, false>;
"<latest[is PolicyState]": $.LinkDesc<$PolicyState, $.Cardinality.Many, {}, false, false, false, false>;
"<latest[is Policy]": $.LinkDesc<$Policy, $.Cardinality.Many, {}, false, false, false, false>;
"<latest[is RemovedPolicy]": $.LinkDesc<$RemovedPolicy, $.Cardinality.Many, {}, false, false, false, false>;
"<spentBy[is Transferlike]": $.LinkDesc<$Transferlike, $.Cardinality.Many, {}, false, false, false, false>;
"<spentBy[is TransferApproval]": $.LinkDesc<$TransferApproval, $.Cardinality.Many, {}, false, false, false, false>;
"<policy[is Proposal]": $.LinkDesc<$Proposal, $.Cardinality.Many, {}, false, false, false, false>;
"<latest": $.LinkDesc<$.ObjectType, $.Cardinality.Many, {}, false, false, false, false>;
"<policies[is Account]": $.LinkDesc<$Account, $.Cardinality.Many, {}, false, false, false, false>;
"<policies": $.LinkDesc<$.ObjectType, $.Cardinality.Many, {}, false, false, false, false>;
"<policy": $.LinkDesc<$.ObjectType, $.Cardinality.Many, {}, false, false, false, false>;
"<spentBy": $.LinkDesc<$.ObjectType, $.Cardinality.Many, {}, false, false, false, false>;
Expand Down Expand Up @@ -738,8 +739,8 @@ const TransfersConfig: $.$expr_PathNode<$.TypeSet<$TransfersConfig, $.Cardinalit
export type $UserλShape = $.typeutil.flatten<_std.$Object_8ce8c71ee4fa5f73840c22d7eaa58588λShape & {
"primaryAccount": $.LinkDesc<$Account, $.Cardinality.AtMostOne, {}, false, false, false, false>;
"approvers": $.LinkDesc<$Approver, $.Cardinality.Many, {}, false, true, false, false>;
"accounts": $.LinkDesc<$Account, $.Cardinality.Many, {}, false, true, false, false>;
"contacts": $.LinkDesc<$Contact, $.Cardinality.Many, {}, false, true, false, false>;
"accounts": $.LinkDesc<$Account, $.Cardinality.Many, {}, false, true, false, false>;
"<user[is Approver]": $.LinkDesc<$Approver, $.Cardinality.Many, {}, false, false, false, false>;
"<user[is current_approver]": $.LinkDesc<$current_approver, $.Cardinality.Many, {}, false, false, false, false>;
"<user[is Contact]": $.LinkDesc<$Contact, $.Cardinality.Many, {}, false, false, false, false>;
Expand Down Expand Up @@ -921,33 +922,6 @@ function as_decimal(...args: any[]) {
}) as any;
};

type latestPolicyλFuncExpr<
P1 extends $.TypeSet<$Account>,
P2 extends _.castMaps.orScalarLiteral<$.TypeSet<_std.$number>>,
> = $.$expr_Function<
$Policy, $.cardutil.overrideLowerBound<$.cardutil.multiplyCardinalities<$.cardutil.paramCardinality<P1>, $.cardutil.paramCardinality<P2>>, 'Zero'>
>;
function latestPolicy<
P1 extends $.TypeSet<$Account>,
P2 extends _.castMaps.orScalarLiteral<$.TypeSet<_std.$number>>,
>(
account: P1,
key: P2,
): latestPolicyλFuncExpr<P1, P2>;
function latestPolicy(...args: any[]) {
const {returnType, cardinality, args: positionalArgs, namedArgs} = _.syntax.$resolveOverload('default::latestPolicy', args, _.spec, [
{args: [{typeId: "4d810c9e-2d7f-11ef-b6f3-0fc90c99b135", optional: false, setoftype: false, variadic: false}, {typeId: "00000000-0000-0000-0000-0000000001ff", optional: false, setoftype: false, variadic: false}], returnTypeId: "50abdaa2-2d7f-11ef-92c5-bfd3f231be91", returnTypemod: "OptionalType"},
]);
return _.syntax.$expressionify({
__kind__: $.ExpressionKind.Function,
__element__: returnType,
__cardinality__: cardinality,
__name__: "default::latestPolicy",
__args__: positionalArgs,
__namedargs__: namedArgs,
}) as any;
};

type labelForUserλFuncExpr<
P1 extends _.castMaps.orScalarLiteral<$.TypeSet<_std.$str>>,
P2 extends $.TypeSet<$User>,
Expand Down Expand Up @@ -1026,6 +1000,33 @@ function tokenForUser(...args: any[]) {
}) as any;
};

type latestPolicyλFuncExpr<
P1 extends $.TypeSet<$Account>,
P2 extends _.castMaps.orScalarLiteral<$.TypeSet<_std.$number>>,
> = $.$expr_Function<
$Policy, $.cardutil.overrideLowerBound<$.cardutil.multiplyCardinalities<$.cardutil.paramCardinality<P1>, $.cardutil.paramCardinality<P2>>, 'Zero'>
>;
function latestPolicy<
P1 extends $.TypeSet<$Account>,
P2 extends _.castMaps.orScalarLiteral<$.TypeSet<_std.$number>>,
>(
account: P1,
key: P2,
): latestPolicyλFuncExpr<P1, P2>;
function latestPolicy(...args: any[]) {
const {returnType, cardinality, args: positionalArgs, namedArgs} = _.syntax.$resolveOverload('default::latestPolicy', args, _.spec, [
{args: [{typeId: "4d810c9e-2d7f-11ef-b6f3-0fc90c99b135", optional: false, setoftype: false, variadic: false}, {typeId: "00000000-0000-0000-0000-0000000001ff", optional: false, setoftype: false, variadic: false}], returnTypeId: "50abdaa2-2d7f-11ef-92c5-bfd3f231be91", returnTypemod: "OptionalType"},
]);
return _.syntax.$expressionify({
__kind__: $.ExpressionKind.Function,
__element__: returnType,
__cardinality__: cardinality,
__name__: "default::latestPolicy",
__args__: positionalArgs,
__namedargs__: namedArgs,
}) as any;
};

type tokenλFuncExpr<
P1 extends _.castMaps.orScalarLiteral<$.TypeSet<_std.$str>>,
> = $.$expr_Function<
Expand Down Expand Up @@ -1149,10 +1150,10 @@ type __defaultExports = {
"as_fixed": typeof as_fixed;
"is_member": typeof is_member;
"as_decimal": typeof as_decimal;
"latestPolicy": typeof latestPolicy;
"labelForUser": typeof labelForUser;
"label": typeof label;
"tokenForUser": typeof tokenForUser;
"latestPolicy": typeof latestPolicy;
"token": typeof token;
"global": typeof $default__globals
};
Expand Down Expand Up @@ -1221,10 +1222,10 @@ const __defaultExports: __defaultExports = {
"as_fixed": as_fixed,
"is_member": is_member,
"as_decimal": as_decimal,
"latestPolicy": latestPolicy,
"labelForUser": labelForUser,
"label": label,
"tokenForUser": tokenForUser,
"latestPolicy": latestPolicy,
"token": token,
"global": $default__globals
};
Expand Down
9 changes: 5 additions & 4 deletions api/dbschema/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ export namespace $default {
"implementation": string;
"photo"?: string | null;
"salt": string;
"policies": Policy[];
"approvers": Approver[];
"messages": Message[];
"proposals": Proposal[];
"transactions": Transaction[];
"transfers": Transfer[];
"policies": Policy[];
"approvers": Approver[];
}
export interface Action extends std.$Object {
"functions": ActionFunction[];
Expand Down Expand Up @@ -210,8 +210,9 @@ export namespace $default {
"proposal"?: Transaction | null;
"initState": boolean;
"isDraft": boolean;
"latest"?: Policy | null;
"latest"?: PolicyState | null;
"isActive": boolean;
"isLatest": boolean;
}
export interface Policy extends PolicyState {
"approvers": Approver[];
Expand Down Expand Up @@ -310,8 +311,8 @@ export namespace $default {
export interface User extends std.$Object {
"primaryAccount"?: Account | null;
"approvers": Approver[];
"accounts": Account[];
"contacts": Contact[];
"accounts": Account[];
}
export interface current_approver extends Approver {}
export interface current_user extends User {}
Expand Down
100 changes: 100 additions & 0 deletions api/dbschema/migrations/00002-m1ti6dj.edgeql
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
CREATE MIGRATION m1msez63jkpjpwsku7jrbuu45dovo5hylpmgeylgdlt3temlkyvn7q
ONTO m1flrdckmwin6sg42mvtplf7qh2l6z2kv3bkmutql23bffpz3zdlgq
{
ALTER TYPE default::PolicyState {
CREATE REQUIRED PROPERTY isLatest: std::bool {
SET default := false;
};
};
ALTER FUNCTION default::latestPolicy(account: default::Account, key: std::int64) USING (std::assert_single((SELECT
default::Policy
FILTER
(((.account = account) AND (.key = key)) AND .isLatest)
)));
ALTER TYPE default::PolicyState {
ALTER LINK latest {
USING ((__source__ IF .isLatest ELSE default::latestPolicy(.account, .key)));
};
ALTER PROPERTY isLatest {
CREATE REWRITE
INSERT
USING ((((.activationBlock ?? 0n) > (((SELECT
default::latestPolicy(.account, .key)
)).activationBlock ?? -1n)) IF NOT (__specified__.isLatest) ELSE .isLatest));
};
CREATE INDEX ON ((.account, .key, .isLatest));
CREATE INDEX ON ((.account, .isLatest));
ALTER PROPERTY isActive {
USING ((.isLatest AND .hasBeenActive));
};
};
ALTER TYPE default::Policy {
ALTER TRIGGER update_proposals_when_deleted USING (UPDATE
default::Proposal
FILTER
(((.account = __old__.account) AND (.policy.key = __old__.key)) AND (([IS default::Transaction].status ?= default::TransactionStatus.Pending) OR (EXISTS ([IS default::Message].id) AND NOT (EXISTS ([IS default::Message].signature)))))
SET {
policy := (SELECT
default::Policy FILTER
(.account = __old__.account)
ORDER BY
.isActive ASC
LIMIT
1
)
});
};
ALTER TYPE default::RemovedPolicy {
CREATE TRIGGER update_proposals_when_latest
AFTER UPDATE, INSERT
FOR EACH
WHEN (__new__.isLatest)
DO (UPDATE
default::Proposal
FILTER
(((.account = __new__.account) AND (.policy.key = __new__.key)) AND (([IS default::Transaction].status ?= default::TransactionStatus.Pending) OR (EXISTS ([IS default::Message].id) AND NOT (EXISTS ([IS default::Message].signature)))))
SET {
policy := (SELECT
default::Policy FILTER
(.account = __new__.account)
ORDER BY
.isActive ASC
LIMIT
1
)
});
};
ALTER TYPE default::Policy {
ALTER TRIGGER update_proposals RENAME TO update_proposals_when_latest;
};
ALTER TYPE default::Policy {
DROP TRIGGER link_insert;
ALTER TRIGGER update_proposals_when_latest WHEN (__new__.isLatest);
};
ALTER TYPE default::RemovedPolicy {
DROP TRIGGER rm_policy_draft_link;
DROP TRIGGER update_proposals;
};
ALTER TYPE default::Account {
ALTER LINK policies {
USING (SELECT
.<account[IS default::Policy]
FILTER
.isLatest
);
RESET ON SOURCE DELETE;
RESET ON TARGET DELETE;
};
};
# Migrate PolicyState with new isLatest property
# Latest PolicyState is the one with the highest activationBlock
update PolicyState set {
isLatest := (
with id := .id,
account := .account,
key := .key,
latest := (select detached PolicyState filter .account = account and .key = key order by .activationBlock desc limit 1)
select (id ?= latest.id)
)
};
};
47 changes: 21 additions & 26 deletions api/dbschema/policy.esdl
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,27 @@ module default {
on target delete delete source;
}
activationBlock: bigint { constraint min_value(0n); }
required property initState := (.activationBlock ?= 0);
required property hasBeenActive := exists .activationBlock;
latest := latestPolicy(.account, .key);
required isLatest: bool {
default := false;
rewrite insert using (
((.activationBlock ?? 0n) > ((select latestPolicy(.account, .key)).activationBlock ?? -1n))
if (not __specified__.isLatest) else .isLatest
)
}
required initState := .activationBlock ?= 0;
required hasBeenActive := exists .activationBlock;
required isActive := .isLatest and .hasBeenActive;
required isDraft := exists .draft;
latest := (__source__ if .isLatest else latestPolicy(.account, .key));
draft := assert_single((
with account := __source__.account, key := __source__.key
select detached PolicyState filter .account = account and .key = key and not .hasBeenActive
order by .createdAt desc limit 1
));
required property isActive := (.hasBeenActive and .latest ?= __source__);
required property isDraft := exists .draft;

index on ((.account, .key));
index on ((.account, .key, .isLatest));
index on ((.account, .isLatest));

access policy members_select_insert_update allow select, insert, update
using (is_member(.account));
Expand All @@ -37,15 +46,8 @@ module default {
required allowMessages: bool { default := false; }
required delay: uint32 { default := 0; }

trigger link_insert after insert, update for each
when ((__new__.activationBlock ?? 0) > ((select __new__.account.policies filter .key = __new__.key limit 1).activationBlock ?? -1)) do (
update __new__.account set {
policies := assert_distinct((select __new__.account.policies filter .key != __new__.key) union __new__)
}
);

trigger update_proposals after insert, update for each
when ((__new__.activationBlock ?? 0) > ((select __new__.account.policies filter .key = __new__.key limit 1).activationBlock ?? -1)) do (
trigger update_proposals_when_latest after insert, update for each
when (__new__.isLatest) do (
update Proposal filter .account = __new__.account and .policy.key = __new__.key and
(([is Transaction].status ?= TransactionStatus.Pending) or ((exists [is Message].id) and (not exists [is Message].signature)))
set {
Expand All @@ -57,31 +59,24 @@ module default {
update Proposal filter .account = __old__.account and .policy.key = __old__.key and
(([is Transaction].status ?= TransactionStatus.Pending) or ((exists [is Message].id) and (not exists [is Message].signature)))
set {
policy := (select __old__.account.policies limit 1)
policy := (select Policy filter .account = __old__.account order by .isActive limit 1)
}
)
}

type RemovedPolicy extending PolicyState {
trigger rm_policy_draft_link after insert, update for each
when ((__new__.activationBlock ?? 0) > ((select __new__.account.policies filter .key = __new__.key limit 1).activationBlock ?? -1)) do (
update __new__.account set {
policies := assert_distinct((select __new__.account.policies filter .key != __new__.key))
}
);

trigger update_proposals after insert, update for each
when ((__new__.activationBlock ?? 0) > ((select __new__.account.policies filter .key = __new__.key limit 1).activationBlock ?? -1)) do (
trigger update_proposals_when_latest after insert, update for each
when (__new__.isLatest) do (
update Proposal filter .account = __new__.account and .policy.key = __new__.key and
(([is Transaction].status ?= TransactionStatus.Pending) or ((exists [is Message].id) and (not exists [is Message].signature)))
set {
policy := (select __new__.account.policies limit 1)
policy := (select Policy filter .account = __new__.account order by .isActive limit 1)
}
);
}

function latestPolicy(account: Account, key: int64) -> optional Policy using (
assert_single((select account.policies filter .key = key))
assert_single((select Policy filter .account = account and .key = key and .isLatest))
);

type Action {
Expand Down
Loading
Loading