@wowok/agent-mcp 3.1.7 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/exposure.d.ts +2 -2
- package/dist/config/judgment.d.ts +5 -5
- package/dist/config/rule-engine.d.ts +5 -5
- package/dist/customer/user-preferences.d.ts +2 -2
- package/dist/evaluation/arbitration-game.js +1 -1
- package/dist/evaluation/capability.d.ts +1 -1
- package/dist/evaluation/extract.js +1 -1
- package/dist/evaluation/match-operation.js +1 -1
- package/dist/extensions/industry-pack.d.ts +3 -2
- package/dist/extensions/industry-pack.js +1 -1
- package/dist/extensions/modes.js +1 -1
- package/dist/extensions/registry.js +1 -1
- package/dist/extensions/types.d.ts +1 -0
- package/dist/graph/onchain/analyze.js +1 -1
- package/dist/graph/onchain/analyze.spec.js +1 -1
- package/dist/graph/onchain/edge-schema.js +1 -1
- package/dist/graph/onchain/extract.js +1 -1
- package/dist/graph/onchain/facts.js +1 -1
- package/dist/graph/onchain/field-manifest.js +1 -1
- package/dist/graph/onchain/project-relationship.js +1 -1
- package/dist/graph/onchain/sdk-batch.d.ts +1 -0
- package/dist/graph/onchain/sdk-batch.js +1 -1
- package/dist/graph/onchain/sdk-dataplane.d.ts +1 -0
- package/dist/graph/onchain/sdk-dataplane.js +1 -1
- package/dist/graph/onchain/types.d.ts +1 -1
- package/dist/harness/recover.js +1 -1
- package/dist/keeper/KeeperScan.d.ts +2 -1
- package/dist/keeper/KeeperScan.js +1 -1
- package/dist/keeper/detectors.d.ts +9 -0
- package/dist/keeper/detectors.js +1 -1
- package/dist/keeper/keeper.spec.js +1 -1
- package/dist/keeper/types.d.ts +1 -1
- package/dist/keeper/types.js +1 -1
- package/dist/knowledge/allocation-ledger.d.ts +4 -1
- package/dist/knowledge/allocation-ledger.js +1 -1
- package/dist/knowledge/allocation-puzzle.d.ts +2 -0
- package/dist/knowledge/allocation-puzzle.js +1 -1
- package/dist/knowledge/allocation-risk.d.ts +1 -1
- package/dist/knowledge/allocation-risk.js +1 -1
- package/dist/knowledge/allocation-templates.d.ts +1 -1
- package/dist/knowledge/allocation-templates.js +1 -1
- package/dist/knowledge/arb-risk.d.ts +3 -1
- package/dist/knowledge/arb-risk.js +1 -1
- package/dist/knowledge/arbitration-ledger.js +1 -1
- package/dist/knowledge/arbitration-risk.js +1 -1
- package/dist/knowledge/arbitration-templates.d.ts +1 -0
- package/dist/knowledge/arbitration-templates.js +1 -1
- package/dist/knowledge/audit-rules.d.ts +13 -2
- package/dist/knowledge/audit-rules.js +1 -1
- package/dist/knowledge/baselines/rules/allocation.json +50 -1
- package/dist/knowledge/baselines/rules/arb.json +20 -1
- package/dist/knowledge/baselines/rules/arbitration.json +27 -0
- package/dist/knowledge/baselines/rules/guard.json +75 -2
- package/dist/knowledge/baselines/rules/machine.json +38 -13
- package/dist/knowledge/baselines/rules/order.json +2 -2
- package/dist/knowledge/builtin-templates.d.ts +3 -1
- package/dist/knowledge/builtin-templates.js +1 -1
- package/dist/knowledge/discount-threshold.d.ts +15 -0
- package/dist/knowledge/discount-threshold.js +1 -0
- package/dist/knowledge/event-semantics.js +1 -1
- package/dist/knowledge/fund-layer.js +1 -1
- package/dist/knowledge/getting-started.js +1 -1
- package/dist/knowledge/guard-anchor-reach.d.ts +19 -0
- package/dist/knowledge/guard-anchor-reach.js +1 -0
- package/dist/knowledge/guard-bindings.js +1 -1
- package/dist/knowledge/guard-design-patterns.d.ts +1 -1
- package/dist/knowledge/guard-design-patterns.js +1 -1
- package/dist/knowledge/guard-ledger.js +1 -1
- package/dist/knowledge/guard-lint.js +1 -1
- package/dist/knowledge/guard-render.d.ts +6 -0
- package/dist/knowledge/guard-render.js +1 -1
- package/dist/knowledge/guard-risk.js +1 -1
- package/dist/knowledge/guard-submission-prompt.d.ts +6 -0
- package/dist/knowledge/guard-submission-prompt.js +1 -1
- package/dist/knowledge/guard-templates.d.ts +1 -1
- package/dist/knowledge/guard-templates.js +1 -1
- package/dist/knowledge/guard-translation.js +1 -1
- package/dist/knowledge/index.d.ts +6 -6
- package/dist/knowledge/index.js +1 -1
- package/dist/knowledge/industry-generalizer.d.ts +38 -1
- package/dist/knowledge/industry-generalizer.js +1 -1
- package/dist/knowledge/industry-registry.d.ts +1 -1
- package/dist/knowledge/industry-registry.js +1 -1
- package/dist/knowledge/industry-strategy.js +1 -1
- package/dist/knowledge/jsonrpc-enum.js +1 -1
- package/dist/knowledge/machine-ledger.js +1 -1
- package/dist/knowledge/machine-risk.js +1 -1
- package/dist/knowledge/machine-templates.js +1 -1
- package/dist/knowledge/onchain-constants.d.ts +2 -2
- package/dist/knowledge/onchain-constants.js +1 -1
- package/dist/knowledge/order-ledger.js +1 -1
- package/dist/knowledge/order-templates.js +1 -1
- package/dist/knowledge/permission-ledger.js +1 -1
- package/dist/knowledge/release-sentinel.d.ts +12 -0
- package/dist/knowledge/release-sentinel.js +1 -0
- package/dist/knowledge/repository-write-semantics.d.ts +27 -0
- package/dist/knowledge/repository-write-semantics.js +1 -0
- package/dist/knowledge/rule-node-analyzers.d.ts +6 -0
- package/dist/knowledge/rule-node-analyzers.js +1 -1
- package/dist/knowledge/safety-rules.d.ts +5 -1
- package/dist/knowledge/safety-rules.js +1 -1
- package/dist/knowledge/scenario-modes.d.ts +20 -1
- package/dist/knowledge/scenario-modes.js +1 -1
- package/dist/knowledge/service-allocation-semantics.d.ts +36 -0
- package/dist/knowledge/service-allocation-semantics.js +1 -0
- package/dist/knowledge/strategy-manuals.d.ts +4 -6
- package/dist/knowledge/strategy-manuals.js +1 -1
- package/dist/knowledge/template-loader.d.ts +48 -12
- package/dist/knowledge/template-loader.js +1 -1
- package/dist/knowledge/template-registry.js +1 -1
- package/dist/knowledge/template-scanner.js +1 -1
- package/dist/knowledge/tools-reference.js +1 -1
- package/dist/knowledge/workflow-guidance.d.ts +26 -0
- package/dist/knowledge/workflow-guidance.js +1 -1
- package/dist/monitor/MonitorLoop.js +1 -1
- package/dist/participation/allocation-advice.d.ts +38 -0
- package/dist/participation/allocation-advice.js +1 -0
- package/dist/participation/arbitrator-interest.js +1 -1
- package/dist/participation/customer-interest.js +1 -1
- package/dist/participation/merchant-interest.js +1 -1
- package/dist/participation/radar-core.d.ts +2 -0
- package/dist/persona/types.d.ts +3 -2
- package/dist/persona/types.js +1 -1
- package/dist/playbooks/service-build/business-puzzle.js +1 -1
- package/dist/playbooks/service-build/intent-analyzer.js +1 -1
- package/dist/playbooks/service-build/machine-panorama.js +1 -1
- package/dist/playbooks/service-build/merchant-guide.d.ts +70 -63
- package/dist/playbooks/service-build/merchant-guide.js +1 -1
- package/dist/playbooks/service-build/migration-planner.js +1 -1
- package/dist/playbooks/service-build/mode-actions.d.ts +17 -1
- package/dist/playbooks/service-build/mode-actions.js +1 -1
- package/dist/playbooks/service-build/object-panorama.js +1 -1
- package/dist/playbooks/service-build/participation-radar.js +1 -1
- package/dist/playbooks/service-build/relationship-profile.js +1 -1
- package/dist/playbooks/service-build/reverse-mapping-refund-p0-5.spec.js +1 -0
- package/dist/playbooks/service-build/reverse-mapping.js +1 -1
- package/dist/playbooks/service-build/semantic-graph.d.ts +1 -0
- package/dist/playbooks/service-build/semantic-graph.js +1 -1
- package/dist/playbooks/service-build/service-panorama.js +1 -1
- package/dist/playbooks/service-build/service-quote.d.ts +2 -0
- package/dist/playbooks/service-build/service-quote.js +1 -0
- package/dist/relationship/derivation.d.ts +1 -1
- package/dist/review/index.js +1 -1
- package/dist/role/profiles.js +1 -1
- package/dist/role/types.d.ts +2 -0
- package/dist/role/types.js +1 -1
- package/dist/safety/confirm-gate.js +1 -1
- package/dist/schema/benchmark-migration/index.d.ts +30 -8
- package/dist/schema/benchmark-migration/index.js +1 -1
- package/dist/schema/call/allocation.d.ts +10 -7
- package/dist/schema/call/arbitration.d.ts +1 -1
- package/dist/schema/call/arbitration.js +1 -1
- package/dist/schema/call/base.d.ts +5 -5
- package/dist/schema/call/base.js +1 -1
- package/dist/schema/call/bridge.d.ts +5 -9
- package/dist/schema/call/bridge.js +1 -1
- package/dist/schema/call/contact.d.ts +1 -1
- package/dist/schema/call/demand.d.ts +1 -1
- package/dist/schema/call/guard.d.ts +15 -15
- package/dist/schema/call/handler.js +1 -1
- package/dist/schema/call/machine.d.ts +58 -2
- package/dist/schema/call/machine.js +1 -1
- package/dist/schema/call/order.d.ts +1 -1
- package/dist/schema/call/order.js +1 -1
- package/dist/schema/call/payment.d.ts +1 -1
- package/dist/schema/call/payment.js +1 -1
- package/dist/schema/call/permission.d.ts +1 -1
- package/dist/schema/call/personal.d.ts +1 -1
- package/dist/schema/call/progress.d.ts +1 -1
- package/dist/schema/call/proof.d.ts +2 -2
- package/dist/schema/call/repository.d.ts +1 -1
- package/dist/schema/call/reward.d.ts +1 -1
- package/dist/schema/call/semantic.js +1 -1
- package/dist/schema/call/service.d.ts +87 -25
- package/dist/schema/call/service.js +1 -1
- package/dist/schema/call/treasury.d.ts +1 -1
- package/dist/schema/common/index.js +1 -1
- package/dist/schema/common/tokentype-short-probe.spec.js +1 -0
- package/dist/schema/evaluation/index.d.ts +14 -82
- package/dist/schema/evaluation/index.js +1 -1
- package/dist/schema/goal/index.d.ts +8 -41
- package/dist/schema/goal/planning.d.ts +22 -57
- package/dist/schema/goal/planning.js +1 -1
- package/dist/schema/industry-pack/index.d.ts +15 -0
- package/dist/schema/industry-pack/modes.d.ts +15 -0
- package/dist/schema/industry-pack/modes.js +1 -1
- package/dist/schema/intent-radar/index.d.ts +5 -20
- package/dist/schema/intent-radar/index.js +1 -1
- package/dist/schema/interaction/index.d.ts +1 -1
- package/dist/schema/keeper/index.d.ts +3 -0
- package/dist/schema/keeper/index.js +1 -1
- package/dist/schema/local/index.d.ts +577 -18
- package/dist/schema/local/index.js +1 -1
- package/dist/schema/messenger/index.d.ts +140 -20
- package/dist/schema/messenger/index.js +1 -1
- package/dist/schema/operations.d.ts +97 -35
- package/dist/schema/operations.js +1 -1
- package/dist/schema/persona/index.d.ts +811 -916
- package/dist/schema/persona/index.js +1 -1
- package/dist/schema/query/bi.d.ts +161 -8
- package/dist/schema/query/bi.js +1 -1
- package/dist/schema/query/index.d.ts +49 -30
- package/dist/schema/query/index.js +1 -1
- package/dist/schema/schema-query/index.d.ts +2 -2
- package/dist/schema/workflow/index.d.ts +2 -2
- package/dist/schema-query-impl/index.d.ts +1 -0
- package/dist/schema-query-impl/index.js +1 -1
- package/dist/schemas/account_operation.output.json +8 -4
- package/dist/schemas/account_operation.schema.json +1 -1
- package/dist/schemas/benchmark_migration_operation.output.json +116 -2
- package/dist/schemas/benchmark_migration_operation.schema.json +2 -10
- package/dist/schemas/bridge_operation.output.json +2 -2
- package/dist/schemas/bridge_operation.schema.json +2 -10
- package/dist/schemas/evaluation_operation.output.json +2 -0
- package/dist/schemas/evaluation_operation.schema.json +9 -70
- package/dist/schemas/goal_operation.schema.json +6 -39
- package/dist/schemas/index.json +7 -1
- package/dist/schemas/industry_pack_operation.output.json +87 -4
- package/dist/schemas/intent_radar.output.json +6 -20
- package/dist/schemas/intent_radar.schema.json +1 -0
- package/dist/schemas/keeper_operation.output.json +2 -2
- package/dist/schemas/keeper_operation.schema.json +9 -4
- package/dist/schemas/local_cache_operation.output.json +1536 -0
- package/dist/schemas/local_cache_operation.schema.json +101 -0
- package/dist/schemas/local_history_operation.output.json +2 -2
- package/dist/schemas/local_info_operation.output.json +2 -2
- package/dist/schemas/local_mark_operation.output.json +53 -38
- package/dist/schemas/local_mark_operation.schema.json +1 -0
- package/dist/schemas/messenger_operation.output.json +2 -2
- package/dist/schemas/messenger_operation.schema.json +358 -35
- package/dist/schemas/monitor_events.output.json +2 -2
- package/dist/schemas/monitor_subscription.output.json +2 -2
- package/dist/schemas/onchain_events.output.json +2 -2
- package/dist/schemas/onchain_operations.output.json +6 -6
- package/dist/schemas/onchain_operations.schema.json +237 -64
- package/dist/schemas/onchain_operations_allocation.schema.json +12 -11
- package/dist/schemas/onchain_operations_arbitration.schema.json +16 -16
- package/dist/schemas/onchain_operations_machine.schema.json +27 -5
- package/dist/schemas/onchain_operations_order.schema.json +1 -1
- package/dist/schemas/onchain_operations_payment.schema.json +3 -3
- package/dist/schemas/onchain_operations_reward.schema.json +2 -2
- package/dist/schemas/onchain_operations_service.schema.json +174 -24
- package/dist/schemas/onchain_operations_treasury.schema.json +2 -2
- package/dist/schemas/onchain_table_data.output.json +68 -4
- package/dist/schemas/persona_operation.output.json +11 -88
- package/dist/schemas/persona_operation.schema.json +4 -32
- package/dist/schemas/query_toolkit.output.json +331 -26
- package/dist/schemas/query_toolkit.schema.json +66 -2
- package/dist/tools/handlers/benchmark-migration.js +1 -1
- package/dist/tools/handlers/bridge.js +1 -1
- package/dist/tools/handlers/dispatch-expectations.spec.js +1 -1
- package/dist/tools/handlers/keeper.d.ts +1 -1
- package/dist/tools/handlers/local.d.ts +1 -0
- package/dist/tools/handlers/local.js +1 -1
- package/dist/tools/handlers/messenger.d.ts +9 -2
- package/dist/tools/handlers/messenger.js +1 -1
- package/dist/tools/handlers/name-resolution.d.ts +4 -0
- package/dist/tools/handlers/name-resolution.js +1 -0
- package/dist/tools/handlers/name-resolution.spec.js +1 -0
- package/dist/tools/handlers/onchain-name-registration.d.ts +37 -0
- package/dist/tools/handlers/onchain-name-registration.js +1 -0
- package/dist/tools/handlers/onchain-name-registration.spec.js +1 -0
- package/dist/tools/handlers/onchain.d.ts +1 -0
- package/dist/tools/handlers/onchain.js +1 -1
- package/dist/tools/handlers/query.d.ts +1 -0
- package/dist/tools/handlers/query.js +1 -1
- package/dist/tools/handlers/schema-query.js +1 -1
- package/dist/tools/index.js +1 -1
- package/dist/tools/move-fn-index.gen.js +1 -1
- package/dist/tools/registry/business.js +1 -1
- package/dist/tools/registry/local.js +1 -1
- package/dist/tools/sanitize-description-roundtrip.spec.js +1 -0
- package/dist/tools/sanitize-output.d.ts +1 -0
- package/dist/tools/sanitize-output.js +1 -1
- package/dist/tools/wrap.js +1 -1
- package/package.json +2 -2
- package/dist/knowledge/alloc-audit-policy.spec.js +0 -1
- package/dist/knowledge/event-semantics.spec.js +0 -1
- package/dist/knowledge/facts-sync.spec.js +0 -1
- package/dist/knowledge/guard-design-patterns.spec.js +0 -1
- package/dist/knowledge/guard-eval.spec.js +0 -1
- package/dist/knowledge/rule-node-analyzers.spec.d.ts +0 -1
- package/dist/knowledge/rule-node-analyzers.spec.js +0 -1
- package/dist/knowledge/safety-rules.extract-amount.spec.d.ts +0 -1
- package/dist/knowledge/safety-rules.extract-amount.spec.js +0 -1
- package/dist/knowledge/template-loader.spec.d.ts +0 -1
- package/dist/knowledge/template-loader.spec.js +0 -1
- package/dist/knowledge/template-scanner.spec.d.ts +0 -1
- package/dist/knowledge/template-scanner.spec.js +0 -1
- /package/dist/{knowledge/alloc-audit-policy.spec.d.ts → playbooks/service-build/reverse-mapping-refund-p0-5.spec.d.ts} +0 -0
- /package/dist/{knowledge/event-semantics.spec.d.ts → schema/common/tokentype-short-probe.spec.d.ts} +0 -0
- /package/dist/{knowledge/facts-sync.spec.d.ts → tools/handlers/name-resolution.spec.d.ts} +0 -0
- /package/dist/{knowledge/guard-design-patterns.spec.d.ts → tools/handlers/onchain-name-registration.spec.d.ts} +0 -0
- /package/dist/{knowledge/guard-eval.spec.d.ts → tools/sanitize-description-roundtrip.spec.d.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ScopeSnapshot } from "../monitor/types.js";
|
|
2
|
-
import { type PaymentDetectorDeps, type ProgressDetectorDeps } from "./detectors.js";
|
|
2
|
+
import { type PaymentDetectorDeps, type ProgressDetectorDeps, type SettlementDetectorDeps } from "./detectors.js";
|
|
3
3
|
import { type KeeperStore } from "./KeeperStore.js";
|
|
4
4
|
import { type KeeperTask } from "./types.js";
|
|
5
5
|
export interface KeeperExecutionOutcome {
|
|
@@ -11,6 +11,7 @@ export interface KeeperScanDeps {
|
|
|
11
11
|
store: KeeperStore;
|
|
12
12
|
payment: PaymentDetectorDeps;
|
|
13
13
|
progress: ProgressDetectorDeps;
|
|
14
|
+
settlement: SettlementDetectorDeps;
|
|
14
15
|
execute(input: {
|
|
15
16
|
operation_type: string;
|
|
16
17
|
data: Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{handleOnchainOperations}from'../tools/handlers/onchain.js';import{detectPaymentUnclaimed,detectProgressActionable,realPaymentDetectorDeps,realProgressDetectorDeps}from'./detectors.js';import{keeperStore}from'./KeeperStore.js';import{AUTO_EXECUTABLE_DETECTORS}from'./types.js';async function defaultExecute(a){try{const b=await handleOnchainOperations({'operation_type':a['operation_type'],'data':a['data'],'env':{'account':a['account'],'network':a['network'],'confirmed':!![],'user_intent_phrases':['keeper\x20auto-execute\x20via\x20'+a['via']]}}),c=b?.['structuredContent']?.['result'];if(c?.['type']==='transaction'&&typeof c?.['digest']==='string')return{'ok':!![],'digest':c['digest']};const d=c?.['type']==='error'&&typeof c?.['error']==='string'?c['error']:typeof b?.['structuredContent']?.['message']==='string'?b['structuredContent']['message']:'execution\x20did\x20not\x20produce\x20a\x20transaction';return{'ok':![],'error':String(d)['slice'](0x0,0x1f4)};}catch(f){return{'ok':![],'error':String(f?.['message']??f)['slice'](0x0,0x1f4)};}}export function realKeeperScanDeps(){return{'store':keeperStore,'payment':realPaymentDetectorDeps(),'progress':realProgressDetectorDeps(),'execute':defaultExecute,'now':()=>Date['now'](),'logger':a=>console['error']('[keeper]\x20'+a)};}export async function runKeeperScan(a,b,c,d){const f=c['now'](),g={'scanned':![],'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0,'auto_executed':0x0,'auto_failed':0x0,'duration_ms':0x0};try{const h=await c['store']['getConfig'](a);if(!h['enabled'])return g['reason']='disabled',g;const i=await c['store']['getLastScanAt'](a);if(!d?.['force']&&c['now']()-i<h['scan_interval_ms'])return g['reason']='interval',g;await c['store']['setLastScanAt'](a,c['now']()),g['scanned']=!![];if(h['detectors']['payment_unclaimed'])try{const l=await detectPaymentUnclaimed((b['accounts']??[])['slice'](0x0,h['max_scan_objects']),a,c['payment']),m=await c['store']['upsertDesired'](a,'payment_unclaimed',l,c['now']());g['opened']+=m['opened'],g['refreshed']+=m['refreshed'],g['revived']+=m['revived'],g['superseded']+=m['superseded'];}catch(n){c['logger']('scan\x20'+a+':\x20payment_unclaimed\x20detector\x20failed:\x20'+String(n?.['message']??n));}if(h['detectors']['progress_actionable'])try{const o=await detectProgressActionable(b,a,c['progress'],h['max_scan_objects']),p=await c['store']['upsertDesired'](a,'progress_actionable',o,c['now']());g['opened']+=p['opened'],g['refreshed']+=p['refreshed'],g['revived']+=p['revived'],g['superseded']+=p['superseded'];}catch(q){c['logger']('scan\x20'+a+':\x20progress_actionable\x20detector\x20failed:\x20'+String(q?.['message']??q));}const j=await c['store']['listTasks'](a,{'status':'pending'});let k=h['max_auto_execute_per_scan'];for(const
|
|
1
|
+
import{handleOnchainOperations}from'../tools/handlers/onchain.js';import{detectPaymentUnclaimed,detectProgressActionable,detectSettlementPending,realPaymentDetectorDeps,realProgressDetectorDeps,realSettlementDetectorDeps}from'./detectors.js';import{keeperStore}from'./KeeperStore.js';import{AUTO_EXECUTABLE_DETECTORS}from'./types.js';async function defaultExecute(a){try{const b=await handleOnchainOperations({'operation_type':a['operation_type'],'data':a['data'],'env':{'account':a['account'],'network':a['network'],'confirmed':!![],'user_intent_phrases':['keeper\x20auto-execute\x20via\x20'+a['via']]}}),c=b?.['structuredContent']?.['result'];if(c?.['type']==='transaction'&&typeof c?.['digest']==='string')return{'ok':!![],'digest':c['digest']};const d=c?.['type']==='error'&&typeof c?.['error']==='string'?c['error']:typeof b?.['structuredContent']?.['message']==='string'?b['structuredContent']['message']:'execution\x20did\x20not\x20produce\x20a\x20transaction';return{'ok':![],'error':String(d)['slice'](0x0,0x1f4)};}catch(f){return{'ok':![],'error':String(f?.['message']??f)['slice'](0x0,0x1f4)};}}export function realKeeperScanDeps(){return{'store':keeperStore,'payment':realPaymentDetectorDeps(),'progress':realProgressDetectorDeps(),'settlement':realSettlementDetectorDeps(),'execute':defaultExecute,'now':()=>Date['now'](),'logger':a=>console['error']('[keeper]\x20'+a)};}export async function runKeeperScan(a,b,c,d){const f=c['now'](),g={'scanned':![],'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0,'auto_executed':0x0,'auto_failed':0x0,'duration_ms':0x0};try{const h=await c['store']['getConfig'](a);if(!h['enabled'])return g['reason']='disabled',g;const i=await c['store']['getLastScanAt'](a);if(!d?.['force']&&c['now']()-i<h['scan_interval_ms'])return g['reason']='interval',g;await c['store']['setLastScanAt'](a,c['now']()),g['scanned']=!![];if(h['detectors']['payment_unclaimed'])try{const l=await detectPaymentUnclaimed((b['accounts']??[])['slice'](0x0,h['max_scan_objects']),a,c['payment']),m=await c['store']['upsertDesired'](a,'payment_unclaimed',l,c['now']());g['opened']+=m['opened'],g['refreshed']+=m['refreshed'],g['revived']+=m['revived'],g['superseded']+=m['superseded'];}catch(n){c['logger']('scan\x20'+a+':\x20payment_unclaimed\x20detector\x20failed:\x20'+String(n?.['message']??n));}if(h['detectors']['progress_actionable'])try{const o=await detectProgressActionable(b,a,c['progress'],h['max_scan_objects']),p=await c['store']['upsertDesired'](a,'progress_actionable',o,c['now']());g['opened']+=p['opened'],g['refreshed']+=p['refreshed'],g['revived']+=p['revived'],g['superseded']+=p['superseded'];}catch(q){c['logger']('scan\x20'+a+':\x20progress_actionable\x20detector\x20failed:\x20'+String(q?.['message']??q));}if(h['detectors']['settlement_pending'])try{const s=await detectSettlementPending(b,a,c['settlement'],h['max_scan_objects']),t=await c['store']['upsertDesired'](a,'settlement_pending',s,c['now']());g['opened']+=t['opened'],g['refreshed']+=t['refreshed'],g['revived']+=t['revived'],g['superseded']+=t['superseded'];}catch(u){c['logger']('scan\x20'+a+':\x20settlement_pending\x20detector\x20failed:\x20'+String(u?.['message']??u));}const j=await c['store']['listTasks'](a,{'status':'pending'});let k=h['max_auto_execute_per_scan'];for(const v of j){if(k<=0x0)break;if(!v['operation'])continue;if(!AUTO_EXECUTABLE_DETECTORS['includes'](v['detector']))continue;if(v['last_auto_attempt_at']&&c['now']()-v['last_auto_attempt_at']<h['auto_retry_cooldown_ms'])continue;const w=await c['store']['matchingAutoRules'](a,v['detector'],v['beneficiary']),x=w[0x0];if(!x)continue;k--,await c['store']['markAutoAttempt'](a,v['id'],c['now']());const y=await c['execute']({'operation_type':v['operation']['operation_type'],'data':v['operation']['data'],'account':v['beneficiary'],'network':a,'via':'rule\x20'+x['id']});y['ok']?(await c['store']['resolveTask'](a,v['id'],'auto_executed',c['now'](),y['digest']?'tx\x20'+y['digest']:'executed',x['id']),g['auto_executed']++,c['logger']('auto-executed\x20'+v['dedupe_key']+'\x20via\x20rule\x20'+x['id']+'\x20('+(y['digest']??'no\x20digest')+')')):(await c['store']['resolveTask'](a,v['id'],'execute_failed',c['now'](),y['error']??'unknown\x20execution\x20error',x['id']),g['auto_failed']++,c['logger']('auto-execute\x20failed\x20for\x20'+v['dedupe_key']+':\x20'+(y['error']??'unknown')));}return g;}catch(z){return c['logger']('scan\x20'+a+'\x20failed:\x20'+String(z?.['message']??z)),g['reason']='error',g;}finally{g['duration_ms']=c['now']()-f;}}export async function executeKeeperTask(a,b,c){if(!b['operation'])return{'ok':![],'error':'This\x20task\x20is\x20reminder-only\x20(no\x20keeper-executable\x20operation).\x20'+'Follow\x20its\x20detail\x20text\x20—\x20progress\x20forwards\x20are\x20advanced\x20via\x20workflow_operation.'};const d=await c['execute']({'operation_type':b['operation']['operation_type'],'data':b['operation']['data'],'account':b['beneficiary'],'network':a,'via':'manual'});return d['ok']?await c['store']['resolveTask'](a,b['id'],'manual_executed',c['now'](),d['digest']?'tx\x20'+d['digest']:'executed'):await c['store']['resolveTask'](a,b['id'],'execute_failed',c['now'](),d['error']),d;}
|
|
@@ -19,5 +19,14 @@ export interface ProgressDetectorDeps {
|
|
|
19
19
|
fetchOrderContext(order: string, network: string): Promise<OrderContext | undefined>;
|
|
20
20
|
}
|
|
21
21
|
export declare function detectProgressActionable(scope: ScopeSnapshot, network: string, deps: ProgressDetectorDeps, maxObjects: number): Promise<KeeperDesiredItem[]>;
|
|
22
|
+
export interface SettlementDetectorDeps {
|
|
23
|
+
fetchOrderFields(addrs: string[], network: string): Promise<Map<string, any>>;
|
|
24
|
+
fetchAllocationFields(addrs: string[], network: string): Promise<Map<string, any>>;
|
|
25
|
+
fetchProgressFields(addrs: string[], network: string): Promise<Map<string, any>>;
|
|
26
|
+
fetchMachineNodes(machine: string, network: string): Promise<ParsedMachineNode[]>;
|
|
27
|
+
formatAmount?(balance: bigint, tokenType: string | undefined, network: string): Promise<string | undefined>;
|
|
28
|
+
}
|
|
29
|
+
export declare function detectSettlementPending(scope: ScopeSnapshot, network: string, deps: SettlementDetectorDeps, maxObjects: number): Promise<KeeperDesiredItem[]>;
|
|
22
30
|
export declare function realPaymentDetectorDeps(): PaymentDetectorDeps;
|
|
23
31
|
export declare function realProgressDetectorDeps(): ProgressDetectorDeps;
|
|
32
|
+
export declare function realSettlementDetectorDeps(): SettlementDetectorDeps;
|
package/dist/keeper/detectors.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{query_received,query_objects}from'@wowok/wowok';import{batchQueryObjectsByIds,fetchMachineNodes,fetchOrderContext,fetchPermissionContext}from'../graph/onchain/sdk-batch.js';import{enumerateActionableForwards}from'../knowledge/index.js';import{formatChainValue}from'../knowledge/fund-layer.js';import{formatShortAddress}from'../persona/address-format.js';export async function detectPaymentUnclaimed(a,b,c){const d=[];for(const e of a){const f=e['toLowerCase']();let g=null;try{g=await c['queryUnclaimed'](f,b);}catch{g=null;}if(!g||g['balance']<=0x0n||g['count']<=0x0)continue;let h;try{h=await c['formatAmount']?.(g['balance'],g['token_type'],b);}catch{h=undefined;}const i=h??g['balance']['toString']()+'\x20(smallest\x20unit)';d['push']({'dedupe_key':'payment_unclaimed:'+f,'detector':'payment_unclaimed','beneficiary':f,'operation':{'operation_type':'payment','data':{'receive':!![]}},'title':'Unclaimed\x20funds\x20—\x20'+i+'\x20waiting\x20to\x20be\x20received','detail':g['count']+'\x20CoinWrapper\x20object(s)\x20hold\x20'+i+'\x20for\x20this\x20account.\x20'+'They\x20are\x20owned\x20but\x20NOT\x20spendable\x20until\x20unwrapped.\x20Execute\x20payment\x20{receive:true}\x20'+'as\x20this\x20account\x20to\x20unwrap\x20all\x20of\x20them\x20into\x20the\x20wallet\x20in\x20one\x20transaction\x20(keeper\x20can\x20'+'auto-execute\x20this\x20when\x20a\x20payment_unclaimed\x20auto-exec\x20rule\x20covers\x20the\x20account).','benefit':'Receive\x20'+i+'\x20into\x20your\x20wallet','state_fingerprint':g['count']+':'+g['balance']['toString']()});}return d;}export async function detectProgressActionable(a,b,c,d){const e=(a['order_children']??[])['filter'](n=>n['type']==='progress'&&typeof n['object']==='string')['map'](n=>n['object'])['filter'](n=>n['startsWith']('0x')),f=(a['focus']??[])['map'](n=>n['object'])['filter'](n=>typeof n==='string'&&n['startsWith']('0x')),g=[...new Set([...e,...f])]['slice'](0x0,Math['max'](0x1,d));if(g['length']===0x0||(a['accounts']??[])['length']===0x0)return[];let h;try{h=await c['fetchProgressFields'](g,b);}catch{return[];}const i=new Map(),j=new Map(),k=new Map(),l=a['accounts'],m=[];for(const [n,o]of h){const p=typeof o?.['machine']==='string'?o['machine']:undefined;if(!p)continue;const q=p['toLowerCase']();let r=i['get'](q);if(!r){try{r=await c['fetchMachineNodes'](p,b);}catch{r=[];}i['set'](q,r);}if(r['length']===0x0)continue;let s;if(!j['has'](q)){let z;try{z=await c['fetchMachinePermissionAddr'](p,b);}catch{z=undefined;}let A;if(z)try{A=await c['fetchPermissionContext'](z,b);}catch{A=undefined;}j['set'](q,A);}s=j['get'](q);const t=typeof o?.['task']==='string'?o['task']:undefined;let u;if(t){const B=t['toLowerCase']();if(!k['has'](B))try{k['set'](B,await c['fetchOrderContext'](t,b));}catch{k['set'](B,undefined);}u=k['get'](B);}const v=(Array['isArray'](o?.['namedOperator'])?o['namedOperator']:[])['map'](C=>({'name':String(C?.['name']??''),'operators':(Array['isArray'](C?.['operators'])?C['operators']:[])['map'](D=>String(D))})),w=enumerateActionableForwards(o,r,l,v,u,s),x=typeof o?.['current']==='string'?o['current']:'',y=t?'order\x20'+formatShortAddress(t):'no\x20bound\x20order';for(const C of w){for(const D of C['executable_accounts']){const E=C['threshold']>0x1?'\x20—\x20cooperation\x20threshold\x20'+C['threshold']+'\x20(weight\x20'+C['weight']+');\x20other\x20distinct\x20forwards\x20may\x20still\x20be\x20needed':'',F=C['guard']?'\x20—\x20guard\x20'+formatShortAddress(C['guard'])+'\x20must\x20be\x20satisfied\x20(submissions\x20may\x20be\x20required)':'',G=u&&D===u['builder']['toLowerCase']()?'You\x20are\x20the\x20order\x20owner':C['operator_kind']==='named_operator'?'You\x20hold\x20the\x20named-operator\x20role\x20\x27'+C['named_operator']+'\x27':'You\x20hold\x20the\x20required\x20permission\x20index';m['push']({'dedupe_key':'progress_actionable:'+n+':'+D+':'+C['next_node']+'|'+C['forward'],'detector':'progress_actionable','beneficiary':D,'object':n,'title':'Workflow\x20action\x20available:\x20\x27'+C['forward']+'\x27\x20→\x20'+C['next_node'],'detail':'Progress\x20'+formatShortAddress(n)+'\x20('+y+')\x20sits\x20at\x20node\x20\x27'+x+'\x27.\x20'+(G+'\x20—\x20you\x20can\x20execute\x20forward\x20\x27'+C['forward']+'\x27\x20into\x20\x27'+C['next_node']+'\x27')+(''+E+F+'.\x20Advance\x20it\x20via\x20workflow_operation\x20')+'(action=\x27list\x27\x20to\x20review,\x20action=\x27operate\x27\x20to\x20execute).\x20'+'Who\x20benefits,\x20who\x20pushes:\x20waiting\x20does\x20not\x20move\x20the\x20order\x20—\x20the\x20party\x20that\x20'+'gains\x20from\x20the\x20next\x20step\x20sends\x20the\x20transaction.','benefit':benefitOfNode(C['next_node']),'state_fingerprint':C['weight']+':'+C['threshold']+':'+(C['guard']??'')+':'+C['operator_kind']});}}}return m;}function benefitOfNode(a){if(/(^|_)(completed?|done|finished|received|delivered|accepted|confirmed|finalized|success|approved)(_|$)/i['test'](a))return'Completing\x20this\x20step\x20settles\x20the\x20order\x20—\x20funds\x20are\x20released\x20to\x20the\x20provider';if(/(^|_)(cancel(led)?|refund(ed)?|return(ed|_approved)?)(_|$)/i['test'](a))return'This\x20step\x20routes\x20to\x20cancellation/refund\x20—\x20funds\x20return\x20to\x20the\x20buyer';if(/(^|_)(interrupt(ed)?|exception|dispute(d)?|fail(ed)?|abort(ed)?|reject(ed)?)(_|$)/i['test'](a))return'This\x20step\x20opens\x20the\x20exception\x20path\x20—\x20review\x20before\x20advancing';return'Advancing\x20keeps\x20the\x20order\x20moving\x20toward\x20settlement';}export function realPaymentDetectorDeps(){return{'queryUnclaimed':async(a,b)=>{const c=await query_received({'name_or_address':{'name_or_address':a},'type':'CoinWrapper','network':b});if(!c||typeof c!=='object'||!Array['isArray'](c['received']))return null;const d=typeof c['balance']==='bigint'?c['balance']:BigInt(c['balance']??0x0);return{'balance':d,'count':c['received']['length'],'token_type':typeof c['token_type']==='string'&&c['token_type']?c['token_type']:undefined};},'formatAmount':async(a,b,c)=>{if(!b)return undefined;const e=await formatChainValue(a,b,c),f=e['symbol']?'\x20'+e['symbol']:'';return e['precision_known']?''+e['display']+f:''+e['raw']+f;}};}export function realProgressDetectorDeps(){return{'fetchProgressFields':async(a,b)=>{const c=await batchQueryObjectsByIds(a,b,![]),e=new Map();for(const f of c??[]){const g=f?.['data']??f;if(f?.['type']!=='Progress')continue;const h=String(f?.['query_name']??f?.['object']??'')['toLowerCase']();if(h)e['set'](h,g);}return e;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'fetchMachinePermissionAddr':async(a,b)=>{const c=await query_objects({'objects':[a],'network':b}),d=c?.['objects']?.[0x0],e=(d?.['data']??d)?.['permission'];return typeof e==='string'&&e?e:undefined;},'fetchPermissionContext':(a,b)=>fetchPermissionContext(a,b,![]),'fetchOrderContext':(a,b)=>fetchOrderContext(a,b,![])};}
|
|
1
|
+
import{query_received,query_objects}from'@wowok/wowok';import{batchQueryObjectsByIds,fetchMachineNodes,fetchOrderContext,fetchPermissionContext}from'../graph/onchain/sdk-batch.js';import{extractCoinType}from'../graph/onchain/extract.js';import{enumerateActionableForwards}from'../knowledge/index.js';import{formatChainValue}from'../knowledge/fund-layer.js';import{formatShortAddress}from'../persona/address-format.js';export async function detectPaymentUnclaimed(a,b,c){const d=[];for(const e of a){const f=e['toLowerCase']();let g=null;try{g=await c['queryUnclaimed'](f,b);}catch{g=null;}if(!g||g['balance']<=0x0n||g['count']<=0x0)continue;let h;try{h=await c['formatAmount']?.(g['balance'],g['token_type'],b);}catch{h=undefined;}const i=h??g['balance']['toString']()+'\x20(smallest\x20unit)';d['push']({'dedupe_key':'payment_unclaimed:'+f,'detector':'payment_unclaimed','beneficiary':f,'operation':{'operation_type':'payment','data':{'receive':!![]}},'title':'Unclaimed\x20funds\x20—\x20'+i+'\x20waiting\x20to\x20be\x20received','detail':g['count']+'\x20CoinWrapper\x20object(s)\x20hold\x20'+i+'\x20for\x20this\x20account.\x20'+'They\x20are\x20owned\x20but\x20NOT\x20spendable\x20until\x20unwrapped.\x20Execute\x20payment\x20{receive:true}\x20'+'as\x20this\x20account\x20to\x20unwrap\x20all\x20of\x20them\x20into\x20the\x20wallet\x20in\x20one\x20transaction\x20(keeper\x20can\x20'+'auto-execute\x20this\x20when\x20a\x20payment_unclaimed\x20auto-exec\x20rule\x20covers\x20the\x20account).','benefit':'Receive\x20'+i+'\x20into\x20your\x20wallet','state_fingerprint':g['count']+':'+g['balance']['toString']()});}return d;}export async function detectProgressActionable(a,b,c,d){const e=(a['order_children']??[])['filter'](n=>n['type']==='progress'&&typeof n['object']==='string')['map'](n=>n['object'])['filter'](n=>n['startsWith']('0x')),f=(a['focus']??[])['map'](n=>n['object'])['filter'](n=>typeof n==='string'&&n['startsWith']('0x')),g=[...new Set([...e,...f])]['slice'](0x0,Math['max'](0x1,d));if(g['length']===0x0||(a['accounts']??[])['length']===0x0)return[];let h;try{h=await c['fetchProgressFields'](g,b);}catch{return[];}const i=new Map(),j=new Map(),k=new Map(),l=a['accounts'],m=[];for(const [n,o]of h){const p=typeof o?.['machine']==='string'?o['machine']:undefined;if(!p)continue;const q=p['toLowerCase']();let r=i['get'](q);if(!r){try{r=await c['fetchMachineNodes'](p,b);}catch{r=[];}i['set'](q,r);}if(r['length']===0x0)continue;let s;if(!j['has'](q)){let z;try{z=await c['fetchMachinePermissionAddr'](p,b);}catch{z=undefined;}let A;if(z)try{A=await c['fetchPermissionContext'](z,b);}catch{A=undefined;}j['set'](q,A);}s=j['get'](q);const t=typeof o?.['task']==='string'?o['task']:undefined;let u;if(t){const B=t['toLowerCase']();if(!k['has'](B))try{k['set'](B,await c['fetchOrderContext'](t,b));}catch{k['set'](B,undefined);}u=k['get'](B);}const v=(Array['isArray'](o?.['namedOperator'])?o['namedOperator']:[])['map'](C=>({'name':String(C?.['name']??''),'operators':(Array['isArray'](C?.['operators'])?C['operators']:[])['map'](D=>String(D))})),w=enumerateActionableForwards(o,r,l,v,u,s),x=typeof o?.['current']==='string'?o['current']:'',y=t?'order\x20'+formatShortAddress(t):'no\x20bound\x20order';for(const C of w){for(const D of C['executable_accounts']){const E=C['threshold']>0x1?'\x20—\x20cooperation\x20threshold\x20'+C['threshold']+'\x20(weight\x20'+C['weight']+');\x20other\x20distinct\x20forwards\x20may\x20still\x20be\x20needed':'',F=C['guard']?'\x20—\x20guard\x20'+formatShortAddress(C['guard'])+'\x20must\x20be\x20satisfied\x20(submissions\x20may\x20be\x20required)':'',G=u&&D===u['builder']['toLowerCase']()?'You\x20are\x20the\x20order\x20owner':C['operator_kind']==='named_operator'?'You\x20hold\x20the\x20named-operator\x20role\x20\x27'+C['named_operator']+'\x27':'You\x20hold\x20the\x20required\x20permission\x20index';m['push']({'dedupe_key':'progress_actionable:'+n+':'+D+':'+C['next_node']+'|'+C['forward'],'detector':'progress_actionable','beneficiary':D,'object':n,'title':'Workflow\x20action\x20available:\x20\x27'+C['forward']+'\x27\x20→\x20'+C['next_node'],'detail':'Progress\x20'+formatShortAddress(n)+'\x20('+y+')\x20sits\x20at\x20node\x20\x27'+x+'\x27.\x20'+(G+'\x20—\x20you\x20can\x20execute\x20forward\x20\x27'+C['forward']+'\x27\x20into\x20\x27'+C['next_node']+'\x27')+(''+E+F+'.\x20Advance\x20it\x20via\x20workflow_operation\x20')+'(action=\x27list\x27\x20to\x20review,\x20action=\x27operate\x27\x20to\x20execute).\x20'+'Who\x20benefits,\x20who\x20pushes:\x20waiting\x20does\x20not\x20move\x20the\x20order\x20—\x20the\x20party\x20that\x20'+'gains\x20from\x20the\x20next\x20step\x20sends\x20the\x20transaction.','benefit':benefitOfNode(C['next_node']),'state_fingerprint':C['weight']+':'+C['threshold']+':'+(C['guard']??'')+':'+C['operator_kind']});}}}return m;}function benefitOfNode(a){if(/(^|_)(completed?|done|finished|received|delivered|accepted|confirmed|finalized|success|approved)(_|$)/i['test'](a))return'Completing\x20this\x20step\x20settles\x20the\x20order\x20—\x20funds\x20are\x20released\x20to\x20the\x20provider';if(/(^|_)(cancel(led)?|refund(ed)?|return(ed|_approved)?)(_|$)/i['test'](a))return'This\x20step\x20routes\x20to\x20cancellation/refund\x20—\x20funds\x20return\x20to\x20the\x20buyer';if(/(^|_)(interrupt(ed)?|exception|dispute(d)?|fail(ed)?|abort(ed)?|reject(ed)?)(_|$)/i['test'](a))return'This\x20step\x20opens\x20the\x20exception\x20path\x20—\x20review\x20before\x20advancing';return'Advancing\x20keeps\x20the\x20order\x20moving\x20toward\x20settlement';}const REFUND_FLAVOR_RE=/(^|_)(cancel(led)?|refund(ed)?|return(ed|_approved)?|expired)(_|$)/i;export async function detectSettlementPending(a,b,c,e){const f=(a['accounts']??[])['map'](s=>s['toLowerCase']());if(f['length']===0x0)return[];const g=(a['orders']??[])['slice'](0x0,Math['max'](0x1,e));if(g['length']===0x0)return[];const h=g['map'](s=>s['order'])['filter'](s=>typeof s==='string'&&s['startsWith']('0x'));let i;try{i=await c['fetchOrderFields'](h,b);}catch{return[];}const j=[],k=[];for(const s of i['values']()){const t=s?.['data']??s;if(typeof t?.['allocation']==='string'&&t['allocation']['startsWith']('0x'))j['push'](t['allocation']);if(typeof t?.['progress']==='string'&&t['progress']['startsWith']('0x'))k['push'](t['progress']);}let l=new Map(),m=new Map();try{l=await c['fetchAllocationFields']([...new Set(j)],b);}catch{return[];}try{m=await c['fetchProgressFields']([...new Set(k)],b);}catch{m=new Map();}const o=new Set((a['services']??[])['map'](u=>u['toLowerCase']())),q=new Map(),r=[];for(const [u,v]of i){const w=v?.['data']??v,x=typeof w?.['allocation']==='string'?w['allocation']:undefined;if(!x)continue;const y=l['get'](x['toLowerCase']());if(!y)continue;const z=y?.['data']??y,A=typeof z['balance']==='bigint'?z['balance']:BigInt(z['balance']??0x0);if(A<=0x0n)continue;const B=Array['isArray'](z['payment'])?z['payment']:[];if(B['length']>0x0)continue;const C=typeof w?.['progress']==='string'?w['progress']:undefined,D=C?m['get'](C['toLowerCase']()):undefined,E=typeof D?.['current']==='string'?D['current']:'',F=typeof D?.['machine']==='string'?D['machine']:typeof w?.['machine']==='string'?w['machine']:undefined;if(!E||!F)continue;let G=q['get'](F['toLowerCase']());if(!G){try{G=await c['fetchMachineNodes'](F,b);}catch{G=[];}q['set'](F['toLowerCase'](),G);}if(G['length']===0x0)continue;const H=new Set();for(const P of G){for(const Q of P['pairs']){if((Q['forwards']??[])['length']>0x0)H['add'](P['name']);}}if(H['has'](E))continue;const I=REFUND_FLAVOR_RE['test'](E),J=[];if(I){const R=typeof w?.['builder']==='string'?w['builder']['toLowerCase']():'';if(R&&f['includes'](R))J['push'](R);}else{const S=typeof w?.['service']==='string'?w['service']['toLowerCase']():'';if(S&&o['has'](S))J['push'](...f);}if(J['length']===0x0)continue;const K=(Array['isArray'](z['allocators']?.['allocators'])?z['allocators']['allocators']:[])['map'](T=>String(T?.['guard']??''))['filter'](T=>T),L=K['length']>0x0?'Candidate\x20settle\x20guards\x20on\x20this\x20pool:\x20'+K['map'](T=>formatShortAddress(T))['join'](',\x20')+'.':'This\x20pool\x20exposes\x20no\x20readable\x20allocator\x20guards\x20—\x20inspect\x20it\x20before\x20acting.';let M;try{M=await c['formatAmount']?.(A,extractCoinType(y?.['type_raw']),b);}catch{M=undefined;}const N=M??A['toString']()+'\x20(smallest\x20unit)',O=I?'refund/cancel':'completion';for(const T of J){r['push']({'dedupe_key':'settlement_pending:'+u+':'+x,'detector':'settlement_pending','beneficiary':T,'object':x,'title':'Unsettled\x20escrow\x20—\x20'+N+'\x20on\x20a\x20'+O+'\x20terminal','detail':'Order\x20'+formatShortAddress(u)+'\x20sits\x20on\x20terminal\x20node\x20\x27'+E+'\x27\x20but\x20its\x20Allocation\x20'+(formatShortAddress(x)+'\x20still\x20holds\x20'+N+'\x20and\x20has\x20emitted\x20no\x20Payment.\x20The\x20chain\x20never\x20')+('auto-settles:\x20someone\x20must\x20trigger\x20the\x20matching\x20guard.\x20'+L+'\x20Execute\x20via\x20allocation_operation\x20')+'(operation_type=\x27allocation\x27,\x20alloc_by_guard=<guard>)\x20as\x20an\x20account\x20that\x20can\x20satisfy\x20the\x20guard,\x20then\x20'+'recipients\x20claim\x20their\x20CoinWrappers\x20(payment\x20receive).\x20Trigger\x20ONCE\x20and\x20verify\x20the\x20pool\x20drained\x20—\x20a\x20'+'fully-drained\x20pool\x20aborts\x20on\x20re-trigger,\x20but\x20a\x20max-capped\x20pool\x20re-splits\x20the\x20remainder.\x20'+'Who\x20benefits,\x20who\x20pushes:\x20waiting\x20keeps\x20the\x20funds\x20frozen\x20and\x20leaves\x20the\x20dispute\x20window\x20open.','benefit':'Release\x20'+N+'\x20from\x20escrow\x20to\x20its\x20rightful\x20recipients','state_fingerprint':A['toString']()+':'+B['length']+':'+E});}}return r;}export function realPaymentDetectorDeps(){return{'queryUnclaimed':async(a,b)=>{const c=await query_received({'name_or_address':{'name_or_address':a},'type':'CoinWrapper','network':b});if(!c||typeof c!=='object'||!Array['isArray'](c['received']))return null;const d=typeof c['balance']==='bigint'?c['balance']:BigInt(c['balance']??0x0);return{'balance':d,'count':c['received']['length'],'token_type':typeof c['token_type']==='string'&&c['token_type']?c['token_type']:undefined};},'formatAmount':async(a,b,c)=>{if(!b)return undefined;const e=await formatChainValue(a,b,c),f=e['symbol']?'\x20'+e['symbol']:'';return e['precision_known']?''+e['display']+f:''+e['raw']+f;}};}export function realProgressDetectorDeps(){return{'fetchProgressFields':async(a,b)=>{const c=await batchQueryObjectsByIds(a,b,![]),e=new Map();for(const f of c??[]){const g=f?.['data']??f;if(f?.['type']!=='Progress')continue;const h=String(f?.['query_name']??f?.['object']??'')['toLowerCase']();if(h)e['set'](h,g);}return e;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'fetchMachinePermissionAddr':async(a,b)=>{const c=await query_objects({'objects':[a],'network':b}),d=c?.['objects']?.[0x0],e=(d?.['data']??d)?.['permission'];return typeof e==='string'&&e?e:undefined;},'fetchPermissionContext':(a,b)=>fetchPermissionContext(a,b,![]),'fetchOrderContext':(a,b)=>fetchOrderContext(a,b,![])};}async function fieldsByType(a,b,c){const d=await batchQueryObjectsByIds(a,b,![]),e=new Map();for(const f of d??[]){if(f?.['type']!==c)continue;const g=String(f?.['query_name']??f?.['object']??'')['toLowerCase']();if(g)e['set'](g,f);}return e;}export function realSettlementDetectorDeps(){return{'fetchOrderFields':(a,b)=>fieldsByType(a,b,'Order'),'fetchAllocationFields':(a,b)=>fieldsByType(a,b,'Allocation'),'fetchProgressFields':async(a,b)=>{const c=await fieldsByType(a,b,'Progress'),d=new Map();for(const [e,f]of c)d['set'](e,f?.['data']??f);return d;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'formatAmount':async(a,b,c)=>{if(!b)return undefined;const e=await formatChainValue(a,b,c),f=e['symbol']?'\x20'+e['symbol']:'';return e['precision_known']?''+e['display']+f:''+e['raw']+f;}};}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{describe,expect,it}from'vitest';import{KeeperStore}from'./KeeperStore.js';import{detectPaymentUnclaimed,detectProgressActionable}from'./detectors.js';import{executeKeeperTask,runKeeperScan}from'./KeeperScan.js';import{clampKeeperConfig,defaultKeeperConfig,KEEPER_MIN}from'./types.js';const NET='testnet',ACCT='0xaaa111',OTHER='0xbbb222';function memStorage(){const a=new Map();return{'get':async b=>a['get'](b),'put':async(b,c)=>void a['set'](b,c)};}function makeStore(){return new KeeperStore(memStorage());}function paymentItem(a,b,c=0x1){return{'dedupe_key':'payment_unclaimed:'+a,'detector':'payment_unclaimed','beneficiary':a,'operation':{'operation_type':'payment','data':{'receive':!![]}},'title':'Unclaimed\x20funds\x20—\x20'+b+'\x20waiting','state_fingerprint':c+':'+b['toString']()};}function makeScope(a){return{'version':0x1,'resolved_at':0x0,'accounts':[ACCT],'permissions':[],'managed_objects':[],'services':[],'orders':[],'order_children':[],'focus':[],'index':{},...a};}describe('keeper\x20config',()=>{it('returns\x20safe\x20defaults:\x20reminders\x20ON,\x20auto\x20rules\x20none',async()=>{const a=makeStore(),b=await a['getConfig'](NET);expect(b['enabled'])['toBe'](!![]),expect(b['detectors']['payment_unclaimed'])['toBe'](!![]),expect(b['detectors']['progress_actionable'])['toBe'](!![]),expect(await a['listRules'](NET))['toEqual']([]);}),it('config_set\x20patch\x20merges\x20detectors\x20individually',async()=>{const a=makeStore(),b=await a['saveConfig'](NET,{'detectors':{'payment_unclaimed':![]}});expect(b['detectors']['payment_unclaimed'])['toBe'](![]),expect(b['detectors']['progress_actionable'])['toBe'](!![]);const c=await a['getConfig'](NET);expect(c['detectors']['payment_unclaimed'])['toBe'](![]),expect(c['detectors']['progress_actionable'])['toBe'](!![]);}),it('clamps\x20numeric\x20bounds\x20(cost/gas\x20guards)',()=>{const a=clampKeeperConfig({...defaultKeeperConfig(),'scan_interval_ms':0x1,'max_scan_objects':0x0,'max_auto_execute_per_scan':0x0,'auto_retry_cooldown_ms':0x0});expect(a['scan_interval_ms'])['toBe'](KEEPER_MIN['scan_interval_ms']),expect(a['max_scan_objects'])['toBe'](KEEPER_MIN['max_scan_objects']),expect(a['max_auto_execute_per_scan'])['toBe'](KEEPER_MIN['max_auto_execute_per_scan']),expect(a['auto_retry_cooldown_ms'])['toBe'](KEEPER_MIN['auto_retry_cooldown_ms']);});}),describe('keeper\x20rules',()=>{const a=b=>({'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0,...b});it('matchingAutoRules\x20honors\x20enabled\x20/\x20auto_execute\x20/\x20account\x20coverage',async()=>{const b=makeStore();await b['upsertRule'](NET,a()),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',ACCT))['toHaveLength'](0x1),expect(await b['matchingAutoRules'](NET,'progress_actionable',ACCT))['toHaveLength'](0x0),await b['upsertRule'](NET,a({'id':'krule_2','accounts':[OTHER['toUpperCase']()]})),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',ACCT))['toHaveLength'](0x1),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',OTHER))['toHaveLength'](0x2),await b['upsertRule'](NET,a({'id':'krule_3','enabled':![]})),await b['upsertRule'](NET,a({'id':'krule_4','auto_execute':![]}));const c=await b['matchingAutoRules'](NET,'payment_unclaimed',OTHER);expect(c['map'](d=>d['id'])['sort']())['toEqual'](['krule_1','krule_2']);});}),describe('KeeperStore.upsertDesired',()=>{it('opens\x20new\x20tasks,\x20refreshes\x20on\x20fingerprint\x20change,\x20no\x20churn\x20when\x20identical',async()=>{const a=makeStore();let b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);expect(b)['toEqual']({'opened':0x1,'refreshed':0x0,'revived':0x0,'superseded':0x0}),b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x7d0),expect(b)['toEqual']({'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0}),b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0xfan)],0xbb8),expect(b)['toEqual']({'opened':0x0,'refreshed':0x1,'revived':0x0,'superseded':0x0});const c=(await a['listTasks'](NET))[0x0];expect(c['title'])['toContain']('250'),expect(c['updated_at'])['toBe'](0xbb8);}),it('dismissed\x20stays\x20dismissed\x20for\x20identical\x20state,\x20revives\x20on\x20material\x20change',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'dismissed',0x5dc,'not\x20now');let c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x7d0);expect(c['revived'])['toBe'](0x0),expect((await a['getTask'](NET,b['id']))['status'])['toBe']('dismissed'),c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x190n,0x2)],0xbb8),expect(c['revived'])['toBe'](0x1);const d=await a['getTask'](NET,b['id']);expect(d['status'])['toBe']('pending'),expect(d['resolution'])['toBeUndefined'](),expect(d['resolved_at'])['toBeUndefined']();}),it('executed\x20tasks\x20are\x20terminal\x20—\x20same\x20dedupe_key\x20never\x20re-opens\x20them',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'auto_executed',0x5dc,'tx\x20ABC','krule_1');const c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x1f4n)],0x7d0);expect(c)['toEqual']({'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0});const d=await a['getTask'](NET,b['id']);expect(d['status'])['toBe']('executed'),expect(d['rule_id'])['toBe']('krule_1');}),it('supersedes\x20pending\x20tasks\x20of\x20THIS\x20detector\x20only',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8),await a['upsertDesired'](NET,'progress_actionable',[{'dedupe_key':'progress_actionable:0xp1:0xaaa111:shipped|deliver','detector':'progress_actionable','beneficiary':ACCT,'title':'Workflow\x20action\x20available','state_fingerprint':'1:1::named_operator'}],0x3e8);const b=await a['upsertDesired'](NET,'payment_unclaimed',[],0x7d0);expect(b['superseded'])['toBe'](0x1);const c=await a['listTasks'](NET),d=c['find'](f=>f['detector']==='payment_unclaimed'),e=c['find'](f=>f['detector']==='progress_actionable');expect(d['status'])['toBe']('superseded'),expect(d['resolution'])['toBe']('superseded'),expect(e['status'])['toBe']('pending');}),it('execute_failed\x20keeps\x20the\x20task\x20pending\x20with\x20failure\x20bookkeeping',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'execute_failed',0x1388,'insufficient\x20gas','krule_1');const c=await a['getTask'](NET,b['id']);expect(c['status'])['toBe']('pending'),expect(c['last_auto_attempt_at'])['toBe'](0x1388),expect(c['auto_attempts'])['toBe'](0x1),expect(c['resolution_note'])['toBe']('insufficient\x20gas');});}),describe('detectPaymentUnclaimed',()=>{it('emits\x20a\x20claim-to-self\x20task\x20for\x20accounts\x20with\x20unclaimed\x20wrappers',async()=>{const a=await detectPaymentUnclaimed([ACCT['toUpperCase'](),OTHER,'0xccc333'],NET,{'queryUnclaimed':async c=>{if(c===ACCT)return{'balance':0x64n,'count':0x2,'token_type':'0x2::wow::WOW'};if(c===OTHER)return{'balance':0x0n,'count':0x0};throw new Error('rpc\x20down');},'formatAmount':async()=>'0.0000001\x20WOW'});expect(a)['toHaveLength'](0x1);const b=a[0x0];expect(b['dedupe_key'])['toBe']('payment_unclaimed:'+ACCT),expect(b['beneficiary'])['toBe'](ACCT),expect(b['operation'])['toEqual']({'operation_type':'payment','data':{'receive':!![]}}),expect(b['state_fingerprint'])['toBe']('2:100'),expect(b['title'])['toContain']('0.0000001\x20WOW');}),it('falls\x20back\x20to\x20raw\x20units\x20when\x20formatting\x20fails',async()=>{const a=await detectPaymentUnclaimed([ACCT],NET,{'queryUnclaimed':async()=>({'balance':0x2an,'count':0x1}),'formatAmount':async()=>{throw new Error('no\x20metadata');}});expect(a[0x0]['title'])['toContain']('42\x20(smallest\x20unit)');});}),describe('detectProgressActionable',()=>{const a='0xprog1',b='0xmachine1',c=[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier'}]}]}],d=(g=[])=>({'machine':b,'current':'start','session':g,'namedOperator':[{'name':'courier','operators':[ACCT]}]}),e=g=>({'fetchProgressFields':async()=>new Map([[a,g]]),'fetchMachineNodes':async()=>c,'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined}),f=makeScope({'order_children':[{'type':'progress','object':a}]});it('routes\x20an\x20actionable\x20forward\x20to\x20its\x20named\x20operator',async()=>{const g=await detectProgressActionable(f,NET,e(d()),0x14);expect(g)['toHaveLength'](0x1),expect(g[0x0]['dedupe_key'])['toBe']('progress_actionable:'+a+':'+ACCT+':shipped|deliver'),expect(g[0x0]['beneficiary'])['toBe'](ACCT),expect(g[0x0]['operation'])['toBeUndefined'](),expect(g[0x0]['detail'])['toContain']('workflow_operation');}),it('omits\x20accomplished\x20forwards\x20(single-operator\x20lock)',async()=>{const g=[{'next_node':'shipped','forwards':[{'forward':'deliver','who':ACCT,'accomplished':!![]}]}],h=await detectProgressActionable(f,NET,e(d(g)),0x14);expect(h)['toHaveLength'](0x0);}),it('restricts\x20a\x20held\x20forward\x20to\x20its\x20holder',async()=>{const g=[{'next_node':'shipped','forwards':[{'forward':'deliver','who':OTHER,'accomplished':![]}]}],h=await detectProgressActionable(f,NET,e(d(g)),0x14);expect(h)['toHaveLength'](0x0);}),it('returns\x20nothing\x20when\x20the\x20batch\x20read\x20fails\x20(fail-safe)',async()=>{const g=await detectProgressActionable(f,NET,{...e(d()),'fetchProgressFields':async()=>{throw new Error('rpc\x20down');}},0x14);expect(g)['toEqual']([]);});});function scanDepsFor(a,b){let c=0x2710;const d=[],e={'store':a,'payment':{'queryUnclaimed':async()=>({'balance':0x64n,'count':0x1})},'progress':{'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[],'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined},'execute':async f=>{return d['push']({'operation_type':f['operation_type'],'account':f['account'],'via':f['via']}),{'ok':!![],'digest':'DIGEST1'};},'now':()=>c,'logger':()=>{},...b};return{'deps':e,'executed':d,'advance':f=>{c+=f;},'setClock':f=>{c=f;}};}describe('runKeeperScan',()=>{it('skips\x20when\x20disabled\x20and\x20when\x20inside\x20the\x20cadence\x20interval',async()=>{const a=makeStore(),{deps:b}=scanDepsFor(a);await a['saveConfig'](NET,{'enabled':![]});let c=await runKeeperScan(NET,makeScope(),b);expect(c['scanned'])['toBe'](![]),expect(c['reason'])['toBe']('disabled'),await a['saveConfig'](NET,{'enabled':!![]}),await a['setLastScanAt'](NET,0x2710),c=await runKeeperScan(NET,makeScope(),b),expect(c['scanned'])['toBe'](![]),expect(c['reason'])['toBe']('interval');}),it('auto-executes\x20a\x20payment\x20task\x20ONLY\x20with\x20a\x20covering\x20enabled\x20rule',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a);let d=await runKeeperScan(NET,makeScope(),b,{'force':!![]});expect(d['opened'])['toBe'](0x1),expect(d['auto_executed'])['toBe'](0x0),expect(c)['toHaveLength'](0x0),await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0}),d=await runKeeperScan(NET,makeScope(),b,{'force':!![]}),expect(d['auto_executed'])['toBe'](0x1),expect(c[0x0])['toEqual']({'operation_type':'payment','account':ACCT,'via':'rule\x20krule_1'});const e=(await a['listTasks'](NET))[0x0];expect(e['status'])['toBe']('executed'),expect(e['resolution'])['toBe']('auto_executed'),expect(e['rule_id'])['toBe']('krule_1'),expect(e['resolution_note'])['toContain']('DIGEST1');}),it('never\x20auto-executes\x20progress\x20tasks\x20(reminder-only\x20boundary)',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a,{'payment':{'queryUnclaimed':async()=>null},'progress':{'fetchProgressFields':async()=>new Map([['0xprog1',{'machine':'0xm1','current':'start','session':[],'namedOperator':[{'name':'courier','operators':[ACCT]}]}]]),'fetchMachineNodes':async()=>[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier'}]}]}],'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined}});await a['upsertRule'](NET,{'id':'krule_p','enabled':!![],'detector':'progress_actionable','accounts':[],'auto_execute':!![],'created_at':0x0});const d=await runKeeperScan(NET,makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),b,{'force':!![]});expect(d['opened'])['toBe'](0x1),expect(d['auto_executed'])['toBe'](0x0),expect(c)['toHaveLength'](0x0),expect((await a['listTasks'](NET))[0x0]['status'])['toBe']('pending');}),it('backs\x20off\x20after\x20a\x20failed\x20auto-exec\x20until\x20the\x20cooldown\x20passes',async()=>{const a=makeStore(),b=scanDepsFor(a,{'execute':async()=>({'ok':![],'error':'insufficient\x20gas'})});await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0});let c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]});expect(c['auto_failed'])['toBe'](0x1);const d=(await a['listTasks'](NET))[0x0];expect(d['status'])['toBe']('pending'),expect(d['resolution_note'])['toBe']('insufficient\x20gas'),c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]}),expect(c['auto_failed'])['toBe'](0x0),expect(c['auto_executed'])['toBe'](0x0),b['advance'](0x1f*0xea60),c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]}),expect(c['auto_failed'])['toBe'](0x1);}),it('caps\x20auto-executions\x20per\x20scan\x20(gas\x20guard)',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a);await a['saveConfig'](NET,{'max_auto_execute_per_scan':0x1}),await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0});const d=makeScope({'accounts':[ACCT,OTHER]}),e=await runKeeperScan(NET,d,b,{'force':!![]});expect(e['opened'])['toBe'](0x2),expect(e['auto_executed'])['toBe'](0x1),expect(c)['toHaveLength'](0x1),expect(await a['listTasks'](NET,{'status':'pending'}))['toHaveLength'](0x1);});}),describe('executeKeeperTask\x20(manual)',()=>{it('resolves\x20a\x20payment\x20task\x20as\x20manual_executed',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0],{deps:c}=scanDepsFor(a),d=await executeKeeperTask(NET,b,c);expect(d['ok'])['toBe'](!![]);const e=await a['getTask'](NET,b['id']);expect(e['status'])['toBe']('executed'),expect(e['resolution'])['toBe']('manual_executed');}),it('refuses\x20reminder-only\x20tasks\x20(progress)\x20with\x20guidance',async()=>{const a=makeStore(),{deps:b}=scanDepsFor(a),c={'id':'ktask_x','dedupe_key':'progress_actionable:0xp:0xaaa111:shipped|deliver','detector':'progress_actionable','network':NET,'beneficiary':ACCT,'title':'Workflow\x20action\x20available','state_fingerprint':'1:1::named_operator','status':'pending','created_at':0x0,'updated_at':0x0},d=await executeKeeperTask(NET,c,b);expect(d['ok'])['toBe'](![]),expect(d['error'])['toContain']('reminder-only');});});
|
|
1
|
+
import{describe,expect,it}from'vitest';import{KeeperStore}from'./KeeperStore.js';import{detectPaymentUnclaimed,detectProgressActionable,detectSettlementPending}from'./detectors.js';import{executeKeeperTask,runKeeperScan}from'./KeeperScan.js';import{clampKeeperConfig,defaultKeeperConfig,KEEPER_MIN}from'./types.js';const NET='testnet',ACCT='0xaaa111',OTHER='0xbbb222';function memStorage(){const a=new Map();return{'get':async b=>a['get'](b),'put':async(b,c)=>void a['set'](b,c)};}function makeStore(){return new KeeperStore(memStorage());}function paymentItem(a,b,c=0x1){return{'dedupe_key':'payment_unclaimed:'+a,'detector':'payment_unclaimed','beneficiary':a,'operation':{'operation_type':'payment','data':{'receive':!![]}},'title':'Unclaimed\x20funds\x20—\x20'+b+'\x20waiting','state_fingerprint':c+':'+b['toString']()};}function makeScope(a){return{'version':0x1,'resolved_at':0x0,'accounts':[ACCT],'permissions':[],'managed_objects':[],'services':[],'orders':[],'order_children':[],'focus':[],'index':{},...a};}describe('keeper\x20config',()=>{it('returns\x20safe\x20defaults:\x20reminders\x20ON,\x20auto\x20rules\x20none',async()=>{const a=makeStore(),b=await a['getConfig'](NET);expect(b['enabled'])['toBe'](!![]),expect(b['detectors']['payment_unclaimed'])['toBe'](!![]),expect(b['detectors']['progress_actionable'])['toBe'](!![]),expect(await a['listRules'](NET))['toEqual']([]);}),it('config_set\x20patch\x20merges\x20detectors\x20individually',async()=>{const a=makeStore(),b=await a['saveConfig'](NET,{'detectors':{'payment_unclaimed':![]}});expect(b['detectors']['payment_unclaimed'])['toBe'](![]),expect(b['detectors']['progress_actionable'])['toBe'](!![]);const c=await a['getConfig'](NET);expect(c['detectors']['payment_unclaimed'])['toBe'](![]),expect(c['detectors']['progress_actionable'])['toBe'](!![]);}),it('clamps\x20numeric\x20bounds\x20(cost/gas\x20guards)',()=>{const a=clampKeeperConfig({...defaultKeeperConfig(),'scan_interval_ms':0x1,'max_scan_objects':0x0,'max_auto_execute_per_scan':0x0,'auto_retry_cooldown_ms':0x0});expect(a['scan_interval_ms'])['toBe'](KEEPER_MIN['scan_interval_ms']),expect(a['max_scan_objects'])['toBe'](KEEPER_MIN['max_scan_objects']),expect(a['max_auto_execute_per_scan'])['toBe'](KEEPER_MIN['max_auto_execute_per_scan']),expect(a['auto_retry_cooldown_ms'])['toBe'](KEEPER_MIN['auto_retry_cooldown_ms']);});}),describe('keeper\x20rules',()=>{const a=b=>({'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0,...b});it('matchingAutoRules\x20honors\x20enabled\x20/\x20auto_execute\x20/\x20account\x20coverage',async()=>{const b=makeStore();await b['upsertRule'](NET,a()),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',ACCT))['toHaveLength'](0x1),expect(await b['matchingAutoRules'](NET,'progress_actionable',ACCT))['toHaveLength'](0x0),await b['upsertRule'](NET,a({'id':'krule_2','accounts':[OTHER['toUpperCase']()]})),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',ACCT))['toHaveLength'](0x1),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',OTHER))['toHaveLength'](0x2),await b['upsertRule'](NET,a({'id':'krule_3','enabled':![]})),await b['upsertRule'](NET,a({'id':'krule_4','auto_execute':![]}));const c=await b['matchingAutoRules'](NET,'payment_unclaimed',OTHER);expect(c['map'](d=>d['id'])['sort']())['toEqual'](['krule_1','krule_2']);});}),describe('KeeperStore.upsertDesired',()=>{it('opens\x20new\x20tasks,\x20refreshes\x20on\x20fingerprint\x20change,\x20no\x20churn\x20when\x20identical',async()=>{const a=makeStore();let b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);expect(b)['toEqual']({'opened':0x1,'refreshed':0x0,'revived':0x0,'superseded':0x0}),b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x7d0),expect(b)['toEqual']({'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0}),b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0xfan)],0xbb8),expect(b)['toEqual']({'opened':0x0,'refreshed':0x1,'revived':0x0,'superseded':0x0});const c=(await a['listTasks'](NET))[0x0];expect(c['title'])['toContain']('250'),expect(c['updated_at'])['toBe'](0xbb8);}),it('dismissed\x20stays\x20dismissed\x20for\x20identical\x20state,\x20revives\x20on\x20material\x20change',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'dismissed',0x5dc,'not\x20now');let c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x7d0);expect(c['revived'])['toBe'](0x0),expect((await a['getTask'](NET,b['id']))['status'])['toBe']('dismissed'),c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x190n,0x2)],0xbb8),expect(c['revived'])['toBe'](0x1);const d=await a['getTask'](NET,b['id']);expect(d['status'])['toBe']('pending'),expect(d['resolution'])['toBeUndefined'](),expect(d['resolved_at'])['toBeUndefined']();}),it('executed\x20tasks\x20are\x20terminal\x20—\x20same\x20dedupe_key\x20never\x20re-opens\x20them',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'auto_executed',0x5dc,'tx\x20ABC','krule_1');const c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x1f4n)],0x7d0);expect(c)['toEqual']({'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0});const d=await a['getTask'](NET,b['id']);expect(d['status'])['toBe']('executed'),expect(d['rule_id'])['toBe']('krule_1');}),it('supersedes\x20pending\x20tasks\x20of\x20THIS\x20detector\x20only',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8),await a['upsertDesired'](NET,'progress_actionable',[{'dedupe_key':'progress_actionable:0xp1:0xaaa111:shipped|deliver','detector':'progress_actionable','beneficiary':ACCT,'title':'Workflow\x20action\x20available','state_fingerprint':'1:1::named_operator'}],0x3e8);const b=await a['upsertDesired'](NET,'payment_unclaimed',[],0x7d0);expect(b['superseded'])['toBe'](0x1);const c=await a['listTasks'](NET),d=c['find'](f=>f['detector']==='payment_unclaimed'),e=c['find'](f=>f['detector']==='progress_actionable');expect(d['status'])['toBe']('superseded'),expect(d['resolution'])['toBe']('superseded'),expect(e['status'])['toBe']('pending');}),it('execute_failed\x20keeps\x20the\x20task\x20pending\x20with\x20failure\x20bookkeeping',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'execute_failed',0x1388,'insufficient\x20gas','krule_1');const c=await a['getTask'](NET,b['id']);expect(c['status'])['toBe']('pending'),expect(c['last_auto_attempt_at'])['toBe'](0x1388),expect(c['auto_attempts'])['toBe'](0x1),expect(c['resolution_note'])['toBe']('insufficient\x20gas');});}),describe('detectPaymentUnclaimed',()=>{it('emits\x20a\x20claim-to-self\x20task\x20for\x20accounts\x20with\x20unclaimed\x20wrappers',async()=>{const a=await detectPaymentUnclaimed([ACCT['toUpperCase'](),OTHER,'0xccc333'],NET,{'queryUnclaimed':async c=>{if(c===ACCT)return{'balance':0x64n,'count':0x2,'token_type':'0x2::wow::WOW'};if(c===OTHER)return{'balance':0x0n,'count':0x0};throw new Error('rpc\x20down');},'formatAmount':async()=>'0.0000001\x20WOW'});expect(a)['toHaveLength'](0x1);const b=a[0x0];expect(b['dedupe_key'])['toBe']('payment_unclaimed:'+ACCT),expect(b['beneficiary'])['toBe'](ACCT),expect(b['operation'])['toEqual']({'operation_type':'payment','data':{'receive':!![]}}),expect(b['state_fingerprint'])['toBe']('2:100'),expect(b['title'])['toContain']('0.0000001\x20WOW');}),it('falls\x20back\x20to\x20raw\x20units\x20when\x20formatting\x20fails',async()=>{const a=await detectPaymentUnclaimed([ACCT],NET,{'queryUnclaimed':async()=>({'balance':0x2an,'count':0x1}),'formatAmount':async()=>{throw new Error('no\x20metadata');}});expect(a[0x0]['title'])['toContain']('42\x20(smallest\x20unit)');});}),describe('detectProgressActionable',()=>{const a='0xprog1',b='0xmachine1',c=[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier'}]}]}],d=(g=[])=>({'machine':b,'current':'start','session':g,'namedOperator':[{'name':'courier','operators':[ACCT]}]}),e=g=>({'fetchProgressFields':async()=>new Map([[a,g]]),'fetchMachineNodes':async()=>c,'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined}),f=makeScope({'order_children':[{'type':'progress','object':a}]});it('routes\x20an\x20actionable\x20forward\x20to\x20its\x20named\x20operator',async()=>{const g=await detectProgressActionable(f,NET,e(d()),0x14);expect(g)['toHaveLength'](0x1),expect(g[0x0]['dedupe_key'])['toBe']('progress_actionable:'+a+':'+ACCT+':shipped|deliver'),expect(g[0x0]['beneficiary'])['toBe'](ACCT),expect(g[0x0]['operation'])['toBeUndefined'](),expect(g[0x0]['detail'])['toContain']('workflow_operation');}),it('omits\x20accomplished\x20forwards\x20(single-operator\x20lock)',async()=>{const g=[{'next_node':'shipped','forwards':[{'forward':'deliver','who':ACCT,'accomplished':!![]}]}],h=await detectProgressActionable(f,NET,e(d(g)),0x14);expect(h)['toHaveLength'](0x0);}),it('restricts\x20a\x20held\x20forward\x20to\x20its\x20holder',async()=>{const g=[{'next_node':'shipped','forwards':[{'forward':'deliver','who':OTHER,'accomplished':![]}]}],h=await detectProgressActionable(f,NET,e(d(g)),0x14);expect(h)['toHaveLength'](0x0);}),it('returns\x20nothing\x20when\x20the\x20batch\x20read\x20fails\x20(fail-safe)',async()=>{const g=await detectProgressActionable(f,NET,{...e(d()),'fetchProgressFields':async()=>{throw new Error('rpc\x20down');}},0x14);expect(g)['toEqual']([]);});}),describe('detectSettlementPending',()=>{const a='0xorder1',b='0xpool1',c='0xprog1',d='0xmachine1',e='0xsvc1',f=i=>[{'name':'paid','pairs':[{'prev_node':'','threshold':0x1,'forwards':[{'name':'settle','weight':0x1}]}]},{'name':i,'pairs':[{'prev_node':'paid','threshold':0x1,'forwards':[]}]}];function g(i,j,k,l){return{'fetchOrderFields':async()=>new Map([[a,{'type':'Order','object':a,'data':i}]]),'fetchAllocationFields':async()=>new Map([[b,{'type':'Allocation','object':b,'type_raw':'0x2::allocation::Allocation<0x2::coin::COIN>','data':j}]]),'fetchProgressFields':async()=>new Map([[c,k]]),'fetchMachineNodes':async()=>l};}const h={'allocation':b,'progress':c,'machine':d,'service':e,'builder':ACCT};it('routes\x20a\x20completion\x20terminal\x20with\x20an\x20unsettled\x20pool\x20to\x20the\x20merchant\x20account',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[{'guard':'0xgsettle'}]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x1),expect(j[0x0]['beneficiary'])['toBe'](ACCT),expect(j[0x0]['detector'])['toBe']('settlement_pending'),expect(j[0x0]['title'])['toContain']('completion'),expect(j[0x0]['detail'])['toContain']('alloc_by_guard');}),it('routes\x20a\x20refund\x20terminal\x20to\x20the\x20buyer\x20(order\x20builder)\x20account',async()=>{const i=makeScope({'orders':[{'order':a,'role':'buyer'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[{'guard':'0xgrefund'}]}},{'current':'refunded','machine':d},f('refunded')),0x14);expect(j)['toHaveLength'](0x1),expect(j[0x0]['beneficiary'])['toBe'](ACCT),expect(j[0x0]['title'])['toContain']('refund/cancel');}),it('skips\x20a\x20pool\x20already\x20drained\x20(balance\x200)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'0','payment':[],'allocators':{'allocators':[]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('skips\x20a\x20pool\x20that\x20already\x20emitted\x20a\x20Payment',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':['0xpay1'],'allocators':{'allocators':[]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('skips\x20a\x20non-terminal\x20node\x20(still\x20has\x20outgoing\x20forwards)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[]}},{'current':'paid','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('returns\x20nothing\x20when\x20the\x20order\x20batch\x20read\x20fails\x20(fail-safe)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,{...g(h,{'balance':'5000','payment':[]},{'current':'completed','machine':d},f('completed')),'fetchOrderFields':async()=>{throw new Error('rpc\x20down');}},0x14);expect(j)['toEqual']([]);});});function scanDepsFor(a,b){let c=0x2710;const d=[],e={'store':a,'payment':{'queryUnclaimed':async()=>({'balance':0x64n,'count':0x1})},'progress':{'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[],'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined},'settlement':{'fetchOrderFields':async()=>new Map(),'fetchAllocationFields':async()=>new Map(),'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[]},'execute':async f=>{return d['push']({'operation_type':f['operation_type'],'account':f['account'],'via':f['via']}),{'ok':!![],'digest':'DIGEST1'};},'now':()=>c,'logger':()=>{},...b};return{'deps':e,'executed':d,'advance':f=>{c+=f;},'setClock':f=>{c=f;}};}describe('runKeeperScan',()=>{it('skips\x20when\x20disabled\x20and\x20when\x20inside\x20the\x20cadence\x20interval',async()=>{const a=makeStore(),{deps:b}=scanDepsFor(a);await a['saveConfig'](NET,{'enabled':![]});let c=await runKeeperScan(NET,makeScope(),b);expect(c['scanned'])['toBe'](![]),expect(c['reason'])['toBe']('disabled'),await a['saveConfig'](NET,{'enabled':!![]}),await a['setLastScanAt'](NET,0x2710),c=await runKeeperScan(NET,makeScope(),b),expect(c['scanned'])['toBe'](![]),expect(c['reason'])['toBe']('interval');}),it('auto-executes\x20a\x20payment\x20task\x20ONLY\x20with\x20a\x20covering\x20enabled\x20rule',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a);let d=await runKeeperScan(NET,makeScope(),b,{'force':!![]});expect(d['opened'])['toBe'](0x1),expect(d['auto_executed'])['toBe'](0x0),expect(c)['toHaveLength'](0x0),await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0}),d=await runKeeperScan(NET,makeScope(),b,{'force':!![]}),expect(d['auto_executed'])['toBe'](0x1),expect(c[0x0])['toEqual']({'operation_type':'payment','account':ACCT,'via':'rule\x20krule_1'});const e=(await a['listTasks'](NET))[0x0];expect(e['status'])['toBe']('executed'),expect(e['resolution'])['toBe']('auto_executed'),expect(e['rule_id'])['toBe']('krule_1'),expect(e['resolution_note'])['toContain']('DIGEST1');}),it('never\x20auto-executes\x20progress\x20tasks\x20(reminder-only\x20boundary)',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a,{'payment':{'queryUnclaimed':async()=>null},'progress':{'fetchProgressFields':async()=>new Map([['0xprog1',{'machine':'0xm1','current':'start','session':[],'namedOperator':[{'name':'courier','operators':[ACCT]}]}]]),'fetchMachineNodes':async()=>[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier'}]}]}],'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined}});await a['upsertRule'](NET,{'id':'krule_p','enabled':!![],'detector':'progress_actionable','accounts':[],'auto_execute':!![],'created_at':0x0});const d=await runKeeperScan(NET,makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),b,{'force':!![]});expect(d['opened'])['toBe'](0x1),expect(d['auto_executed'])['toBe'](0x0),expect(c)['toHaveLength'](0x0),expect((await a['listTasks'](NET))[0x0]['status'])['toBe']('pending');}),it('backs\x20off\x20after\x20a\x20failed\x20auto-exec\x20until\x20the\x20cooldown\x20passes',async()=>{const a=makeStore(),b=scanDepsFor(a,{'execute':async()=>({'ok':![],'error':'insufficient\x20gas'})});await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0});let c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]});expect(c['auto_failed'])['toBe'](0x1);const d=(await a['listTasks'](NET))[0x0];expect(d['status'])['toBe']('pending'),expect(d['resolution_note'])['toBe']('insufficient\x20gas'),c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]}),expect(c['auto_failed'])['toBe'](0x0),expect(c['auto_executed'])['toBe'](0x0),b['advance'](0x1f*0xea60),c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]}),expect(c['auto_failed'])['toBe'](0x1);}),it('caps\x20auto-executions\x20per\x20scan\x20(gas\x20guard)',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a);await a['saveConfig'](NET,{'max_auto_execute_per_scan':0x1}),await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0});const d=makeScope({'accounts':[ACCT,OTHER]}),e=await runKeeperScan(NET,d,b,{'force':!![]});expect(e['opened'])['toBe'](0x2),expect(e['auto_executed'])['toBe'](0x1),expect(c)['toHaveLength'](0x1),expect(await a['listTasks'](NET,{'status':'pending'}))['toHaveLength'](0x1);});}),describe('executeKeeperTask\x20(manual)',()=>{it('resolves\x20a\x20payment\x20task\x20as\x20manual_executed',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0],{deps:c}=scanDepsFor(a),d=await executeKeeperTask(NET,b,c);expect(d['ok'])['toBe'](!![]);const e=await a['getTask'](NET,b['id']);expect(e['status'])['toBe']('executed'),expect(e['resolution'])['toBe']('manual_executed');}),it('refuses\x20reminder-only\x20tasks\x20(progress)\x20with\x20guidance',async()=>{const a=makeStore(),{deps:b}=scanDepsFor(a),c={'id':'ktask_x','dedupe_key':'progress_actionable:0xp:0xaaa111:shipped|deliver','detector':'progress_actionable','network':NET,'beneficiary':ACCT,'title':'Workflow\x20action\x20available','state_fingerprint':'1:1::named_operator','status':'pending','created_at':0x0,'updated_at':0x0},d=await executeKeeperTask(NET,c,b);expect(d['ok'])['toBe'](![]),expect(d['error'])['toContain']('reminder-only');});});
|
package/dist/keeper/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type KeeperDetectorKind = "payment_unclaimed" | "progress_actionable";
|
|
1
|
+
export type KeeperDetectorKind = "payment_unclaimed" | "progress_actionable" | "settlement_pending";
|
|
2
2
|
export declare const KEEPER_DETECTORS: readonly KeeperDetectorKind[];
|
|
3
3
|
export declare const AUTO_EXECUTABLE_DETECTORS: readonly KeeperDetectorKind[];
|
|
4
4
|
export type KeeperTaskStatus = "pending" | "executed" | "dismissed" | "superseded";
|
package/dist/keeper/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const KEEPER_DETECTORS=['payment_unclaimed','progress_actionable'];export const AUTO_EXECUTABLE_DETECTORS=['payment_unclaimed'];export const KEEPER_DEFAULTS={'scan_interval_ms':0x1d4c0,'max_scan_objects':0x14,'max_auto_execute_per_scan':0x5,'auto_retry_cooldown_ms':0x1b7740};export const KEEPER_MIN={'scan_interval_ms':0x7530,'max_scan_objects':0x1,'max_auto_execute_per_scan':0x1,'auto_retry_cooldown_ms':0xea60};export function defaultKeeperConfig(){return{'enabled':!![],'detectors':{'payment_unclaimed':!![],'progress_actionable':!![]},'scan_interval_ms':KEEPER_DEFAULTS['scan_interval_ms'],'max_scan_objects':KEEPER_DEFAULTS['max_scan_objects'],'max_auto_execute_per_scan':KEEPER_DEFAULTS['max_auto_execute_per_scan'],'auto_retry_cooldown_ms':KEEPER_DEFAULTS['auto_retry_cooldown_ms']};}export function clampKeeperConfig(a){const b=(c,d,e)=>{const f=Number(c);return Number['isFinite'](f)?Math['max'](e,Math['floor'](f)):d;};return{...a,'scan_interval_ms':b(a['scan_interval_ms'],KEEPER_DEFAULTS['scan_interval_ms'],KEEPER_MIN['scan_interval_ms']),'max_scan_objects':b(a['max_scan_objects'],KEEPER_DEFAULTS['max_scan_objects'],KEEPER_MIN['max_scan_objects']),'max_auto_execute_per_scan':b(a['max_auto_execute_per_scan'],KEEPER_DEFAULTS['max_auto_execute_per_scan'],KEEPER_MIN['max_auto_execute_per_scan']),'auto_retry_cooldown_ms':b(a['auto_retry_cooldown_ms'],KEEPER_DEFAULTS['auto_retry_cooldown_ms'],KEEPER_MIN['auto_retry_cooldown_ms'])};}export function newKeeperTaskId(){return'ktask_'+Date['now']()['toString'](0x24)+'_'+Math['random']()['toString'](0x24)['slice'](0x2,0x8);}export function newKeeperRuleId(){return'krule_'+Date['now']()['toString'](0x24)+'_'+Math['random']()['toString'](0x24)['slice'](0x2,0x8);}
|
|
1
|
+
export const KEEPER_DETECTORS=['payment_unclaimed','progress_actionable','settlement_pending'];export const AUTO_EXECUTABLE_DETECTORS=['payment_unclaimed'];export const KEEPER_DEFAULTS={'scan_interval_ms':0x1d4c0,'max_scan_objects':0x14,'max_auto_execute_per_scan':0x5,'auto_retry_cooldown_ms':0x1b7740};export const KEEPER_MIN={'scan_interval_ms':0x7530,'max_scan_objects':0x1,'max_auto_execute_per_scan':0x1,'auto_retry_cooldown_ms':0xea60};export function defaultKeeperConfig(){return{'enabled':!![],'detectors':{'payment_unclaimed':!![],'progress_actionable':!![],'settlement_pending':!![]},'scan_interval_ms':KEEPER_DEFAULTS['scan_interval_ms'],'max_scan_objects':KEEPER_DEFAULTS['max_scan_objects'],'max_auto_execute_per_scan':KEEPER_DEFAULTS['max_auto_execute_per_scan'],'auto_retry_cooldown_ms':KEEPER_DEFAULTS['auto_retry_cooldown_ms']};}export function clampKeeperConfig(a){const b=(c,d,e)=>{const f=Number(c);return Number['isFinite'](f)?Math['max'](e,Math['floor'](f)):d;};return{...a,'scan_interval_ms':b(a['scan_interval_ms'],KEEPER_DEFAULTS['scan_interval_ms'],KEEPER_MIN['scan_interval_ms']),'max_scan_objects':b(a['max_scan_objects'],KEEPER_DEFAULTS['max_scan_objects'],KEEPER_MIN['max_scan_objects']),'max_auto_execute_per_scan':b(a['max_auto_execute_per_scan'],KEEPER_DEFAULTS['max_auto_execute_per_scan'],KEEPER_MIN['max_auto_execute_per_scan']),'auto_retry_cooldown_ms':b(a['auto_retry_cooldown_ms'],KEEPER_DEFAULTS['auto_retry_cooldown_ms'],KEEPER_MIN['auto_retry_cooldown_ms'])};}export function newKeeperTaskId(){return'ktask_'+Date['now']()['toString'](0x24)+'_'+Math['random']()['toString'](0x24)['slice'](0x2,0x8);}export function newKeeperRuleId(){return'krule_'+Date['now']()['toString'](0x24)+'_'+Math['random']()['toString'](0x24)['slice'](0x2,0x8);}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MAX_ALLOCATOR_COUNT } from "@wowok/wowok";
|
|
2
|
-
export type AllocationMode = "Amount" | "Rate" | "Surplus";
|
|
2
|
+
export type AllocationMode = "Amount" | "Rate" | "Surplus" | "RateGross";
|
|
3
3
|
export type RecipientType = "GuardIdentifier" | "Entity" | "Signer";
|
|
4
4
|
export type TriggerSource = "service_order_allocators" | "arbitration_fees" | "standalone";
|
|
5
5
|
export interface AllocationScene {
|
|
@@ -24,6 +24,7 @@ export declare const ALLOCATION_MAX_SHARING_COUNT: 100;
|
|
|
24
24
|
export declare const ALLOCATION_MODE_AMOUNT = 0;
|
|
25
25
|
export declare const ALLOCATION_MODE_RATE = 1;
|
|
26
26
|
export declare const ALLOCATION_MODE_SURPLUS = 2;
|
|
27
|
+
export declare const ALLOCATION_MODE_RATE_GROSS = 3;
|
|
27
28
|
export declare const RATE_TOTAL_FULL = 10000;
|
|
28
29
|
export declare const ALLOCATION_ERROR_CODES: {
|
|
29
30
|
readonly ERECIPIENT_IDENTIFIER_NOT_ADDRESS: 1;
|
|
@@ -41,6 +42,8 @@ export declare const ALLOCATION_ERROR_CODES: {
|
|
|
41
42
|
readonly EAMOUNT_EXCEEDS_MAX: 13;
|
|
42
43
|
readonly EZERO_DISTRIBUTION: 14;
|
|
43
44
|
readonly ERECIPIENT_NOT_FOR_OBJECT: 15;
|
|
45
|
+
readonly E_ONCE_TRIGGERED: 16;
|
|
46
|
+
readonly EMIXED_RATE_BASES: 17;
|
|
44
47
|
};
|
|
45
48
|
export declare const ORDER_ALLOCATION_ALREADY_SPECIFIED = "E_ALLOCATION_ALREADY_SPECIFIED";
|
|
46
49
|
export declare const ALLOCATION_SCENES: AllocationScene[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MAX_SHARING_COUNT,MAX_ALLOCATOR_COUNT}from'@wowok/wowok';export{MAX_ALLOCATOR_COUNT};export const ALLOCATION_MAX_SHARING_COUNT=MAX_SHARING_COUNT;export const ALLOCATION_MODE_AMOUNT=0x0;export const ALLOCATION_MODE_RATE=0x1;export const ALLOCATION_MODE_SURPLUS=0x2;export const RATE_TOTAL_FULL=0x2710;export const ALLOCATION_ERROR_CODES={'ERECIPIENT_IDENTIFIER_NOT_ADDRESS':0x1,'EALLOCATOR_COUNT_EXCEEDED':0x2,'ENO_ALLOCATOR':0x3,'ERATE_NOT_10000':0x4,'EMULTIPLE_SURPLUS':0x5,'ERATE_EXCEEDS_10000':0x6,'EINSUFFICIENT_BALANCE':0x7,'EALLOCATORS_EMPTY':0x8,'ENO_PAYMENT_INFO':0x9,'ESHARING_COUNT_EXCEEDED':0xa,'ESHARING_MODE_INVALID':0xb,'EAMOUNT_BELOW_THRESHOLD':0xc,'EAMOUNT_EXCEEDS_MAX':0xd,'EZERO_DISTRIBUTION':0xe,'ERECIPIENT_NOT_FOR_OBJECT':0xf};export const ORDER_ALLOCATION_ALREADY_SPECIFIED='E_ALLOCATION_ALREADY_SPECIFIED';export const ALLOCATION_SCENES=[{'id':'allocation_standard_three_way_split','name':'Standard\x20three-way\x20split\x20(merchant\x20/\x20platform\x20/\x20logistics)','trigger_source':'service_order_allocators','distribution_strategy':'pure_rate','coin_type_note':'All\x20three\x20Treasury\x20objects\x20must\x20use\x20the\x20same\x20Coin<T>\x20type\x20as\x20the\x20Allocation','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x203\x20Rate\x20sharing\x20items,\x20sum(rates)\x20===\x2010000','Each\x20sharing.who=Entity\x20points\x20to\x20a\x20Treasury\x20address','Guard\x20verifies\x20order.service\x20binding\x20(query\x201563)\x20to\x20prevent\x20cross-project\x20bypass','Guard\x20verifies\x20progress.current_node\x20===\x20\x27Complete\x27'],'dependencies':['Service','Treasury','Guard','Order','Progress','Machine','Payment'],'key_constraints':['F-A-05:\x20sum(rates)\x20===\x2010000\x20(pure\x20Rate\x20mode)','Treasury\x20Permission\x20should\x20match\x20Service\x20Permission\x20(R-A-12)','order_allocators\x20immutable\x20after\x20Service\x20publish\x20(R-A-10)'],'recommended_templates':['T-A-02']},{'id':'allocation_merchant_full_payment','name':'Merchant\x20full\x20payment\x20(single\x20recipient,\x20100%)','trigger_source':'service_order_allocators','distribution_strategy':'pure_rate','coin_type_note':'Simplest\x20configuration\x20—\x20single\x20Treasury\x20or\x20personal\x20address','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'single_relaxed','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x201\x20Rate\x20sharing\x20=\x2010000','Guard\x20only\x20verifies\x20order\x20status\x20(no\x20complex\x20conditions)','who=Entity\x20can\x20be\x20either\x20Treasury\x20or\x20personal\x20wallet'],'dependencies':['Service','Guard','Order','Payment'],'key_constraints':['Simplest\x20allocation\x20configuration','No\x20multi-party\x20coordination\x20required'],'recommended_templates':['T-A-01']},{'id':'allocation_refund_first_surplus_to_merchant','name':'Refund\x20first\x20+\x20surplus\x20to\x20merchant\x20(Amount\x20+\x20Surplus\x20hybrid)','trigger_source':'service_order_allocators','distribution_strategy':'amount_plus_surplus','coin_type_note':'Refund\x20amount\x20must\x20match\x20Coin<T>\x20precision','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Amount','Surplus'],'guard_requirement':'required','non_zero_threshold':!![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x202\x20sharing\x20items','sharing[0]:\x20Amount=refund_value,\x20who=Entity(customer_address)','sharing[1]:\x20Surplus,\x20who=Entity(merchant_treasury)','fix\x20=\x20refund_value\x20(cached\x20Amount\x20sum)','threshold\x20=\x20refund_value\x20(ensure\x20sufficient\x20balance\x20for\x20Amount)'],'dependencies':['Service','Treasury','Guard','Order','Payment'],'key_constraints':['F-A-04:\x20at\x20most\x201\x20Surplus\x20per\x20Allocator','F-A-07:\x20fix\x20>=\x20threshold\x20(Amount\x20sum\x20must\x20cover\x20threshold)','fix\x20must\x20precisely\x20match\x20the\x20refund\x20amount'],'recommended_templates':['T-A-03']},{'id':'allocation_treasury_personal_alternatives','name':'Treasury\x20+\x20Personal\x20alternative\x20strategies\x20(caller-specified\x20guard)','trigger_source':'service_order_allocators','distribution_strategy':'first_match_alternatives','coin_type_note':'Both\x20target\x20addresses\x20must\x20accept\x20the\x20same\x20Coin<T>','typical_allocator_count':0x2,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'multiple_unique','non_zero_threshold':![],'uses_max':![],'common_patterns':['2\x20Allocators,\x20each\x20with\x201\x20Rate=10000\x20sharing','Allocator[0]:\x20guard=guard_treasury,\x20who=Entity(treasury_address)','Allocator[1]:\x20guard=guard_personal,\x20who=Entity(personal_address)','Two\x20Guard\x20objects\x20must\x20be\x20different\x20addresses\x20(R-A-11)','caller-specified\x20guard:\x20caller\x20selects\x20Treasury\x20or\x20Personal\x20path\x20via\x20alloc_by_guard;\x20the\x20Passport\x20hard-verifies\x20the\x20selected\x20Guard\x20(failure\x20aborts\x20with\x20E_VERIFY_FAILED;\x20caller\x20must\x20switch\x20guard\x20and\x20retry)'],'dependencies':['Service','Treasury','Guard','Order','Payment'],'key_constraints':['F-A-14:\x20allocators[].guard\x20must\x20be\x20unique','Treasury\x20Permission\x20should\x20match\x20Service\x20Permission\x20(R-A-12)','Guard\x20A\x20and\x20Guard\x20B\x20may\x20share\x20root/table\x20but\x20must\x20differ\x20in\x20description'],'recommended_templates':['T-A-04']},{'id':'allocation_tiered_by_order_amount','name':'Tiered\x20split\x20by\x20order\x20amount\x20(multi-Allocator\x20amount-threshold\x20switch)','trigger_source':'service_order_allocators','distribution_strategy':'tiered_by_amount','coin_type_note':'Amount\x20threshold\x20uses\x20Coin<T>\x20smallest\x20unit\x20(e.g.\x20MIST\x20for\x20WOW)','typical_allocator_count':0x2,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'multiple_unique','non_zero_threshold':![],'uses_max':![],'common_patterns':['2\x20Allocators\x20triggered\x20by\x20mutually\x20exclusive\x20Guard\x20conditions','Allocator[0]:\x20guard\x20verifies\x20order.amount\x20<\x20threshold,\x20Rate=10000\x20to\x20merchant','Allocator[1]:\x20guard\x20verifies\x20order.amount\x20>=\x20threshold,\x20Rate=8000/2000\x20split','caller-specified\x20guard:\x20caller\x20selects\x20the\x20matching\x20Allocator\x20based\x20on\x20order\x20amount;\x20allocator\x20order\x20is\x20irrelevant','Guard\x20queries\x20order.amount\x20(query\x201561)'],'dependencies':['Service','Treasury','Guard','Order','Payment'],'key_constraints':['Guard\x20conditions\x20must\x20be\x20mutually\x20exclusive\x20(R-A-4-02\x20design\x20clarity)','Caller\x20must\x20select\x20correct\x20guard\x20based\x20on\x20order.amount\x20(no\x20auto-fallback)'],'recommended_templates':['T-A-05']},{'id':'allocation_dynamic_recipient','name':'Multi-role\x20split\x20with\x20dynamic\x20recipient\x20(GuardIdentifier)','trigger_source':'service_order_allocators','distribution_strategy':'dynamic_recipient','coin_type_note':'Passport\x20table\x20must\x20contain\x20address-typed\x20entry\x20at\x20the\x20referenced\x20identifier','typical_allocator_count':0x1,'sharing_who_types':['Entity','GuardIdentifier'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x203\x20Rate\x20sharing\x20items','sharing[0]:\x20Rate=8000,\x20who=Entity(merchant_treasury)','sharing[1]:\x20Rate=1000,\x20who=Entity(platform_treasury)','sharing[2]:\x20Rate=1000,\x20who=GuardIdentifier(0)\x20—\x20resolves\x20from\x20Passport\x20table','Customer\x20submits\x20Passport\x20with\x20referrer\x20address\x20at\x20identifier=0'],'dependencies':['Service','Treasury','Guard','Passport','Order','Payment'],'key_constraints':['F-A-13:\x20Passport\x20table[identifier]\x20must\x20be\x20address\x20type\x20(else\x20ERECIPIENT_IDENTIFIER_NOT_ADDRESS)','Guard\x20must\x20verify\x20Passport\x20completeness','Customer\x20order\x20must\x20include\x20Passport\x20with\x20referrer\x20address'],'recommended_templates':['T-A-06']},{'id':'allocation_arbitration_fees','name':'Arbitration\x20fees\x20split\x20(arbitrator\x20/\x20platform)','trigger_source':'arbitration_fees','distribution_strategy':'pure_rate','coin_type_note':'Coin<T>\x20must\x20match\x20Arbitration\x27s\x20fee\x20Coin\x20type','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Triggered\x20by\x20the\x20Arbitration\x20fee-allocation\x20operation\x20(permission\x20365),\x20direct\x20or\x20Passport\x20path','Single\x20Allocator,\x202\x20Rate\x20sharing\x20items:\x208000\x20arbitrator\x20/\x202000\x20platform','payment_info\x20reuses\x20Arbitration\x27s\x20payment_info','Caller\x20must\x20hold\x20ARBITRATION_FEES_ALLOC=365\x20permission'],'dependencies':['Arbitration','Treasury','Guard','Payment'],'key_constraints':['Independent\x20from\x20Service-order\x20Allocation','Requires\x20ARBITRATION_FEES_ALLOC=365\x20permission'],'recommended_templates':['T-A-08']},{'id':'allocation_refund_to_order','name':'Refund\x20Allocator\x20(100%\x20to\x20Order\x20object)','trigger_source':'service_order_allocators','distribution_strategy':'refund_to_order','coin_type_note':'who=Entity\x20must\x20be\x20the\x20Order\x20object\x20address\x20(NOT\x20a\x20personal\x20wallet)','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x201\x20Rate=10000\x20sharing','who=Entity(order_address)\x20—\x20funds\x20flow\x20back\x20to\x20Order,\x20not\x20personal\x20wallet','Guard\x20verifies\x20customer\x20refund\x20request\x20and\x20eligibility','Customer-side\x20risk\x20assessment\x20adds\x208-point\x20weight\x20(onchain_topology\x20graph\x20evaluation)'],'dependencies':['Service','Guard','Order','Payment'],'key_constraints':['who=Entity\x20MUST\x20be\x20Order\x20object\x20address\x20(not\x20personal\x20address)','Customer\x20due-diligence\x20rewards\x20this\x20configuration\x20(8-point\x20weight)','Refund\x20funds\x20return\x20to\x20Order\x20for\x20downstream\x20handling'],'recommended_templates':['T-A-07']},{'id':'allocation_max_capped_retain','name':'Max-capped\x20allocation\x20(retain\x20residual\x20balance)','trigger_source':'service_order_allocators','distribution_strategy':'max_capped','coin_type_note':'max\x20field\x20uses\x20Coin<T>\x20smallest\x20unit','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Amount','Rate'],'guard_requirement':'required','non_zero_threshold':!![],'uses_max':!![],'common_patterns':['Single\x20Allocator\x20with\x20max\x20field\x20set','max\x20triple\x20role:\x20Amount\x20cap\x20+\x20Rate\x20base\x20+\x20Surplus\x20cap','Amount\x20sharing\x20consumes\x20fix;\x20Rate\x20sharing\x20uses\x20(max\x20-\x20fix)\x20as\x20base','Residual\x20balance\x20remains\x20in\x20Allocation\x20for\x20subsequent\x20alloc()\x20calls'],'dependencies':['Service','Treasury','Guard','Order','Payment'],'key_constraints':['F-A-08:\x20Amount\x20sum\x20<=\x20max\x20(EAMOUNT_EXCEEDS_MAX)','max\x20-\x20fix\x20becomes\x20Rate\x20base\x20(NOT\x20balance\x20-\x20fix)','Residual\x20balance\x20may\x20be\x20claimed\x20by\x20re-triggering\x20alloc()'],'recommended_templates':[]},{'id':'allocation_multi_node_trigger','name':'Multi-Machine-node\x20triggered\x20allocation\x20(Complete\x20/\x20Refund\x20/\x20Lost)','trigger_source':'service_order_allocators','distribution_strategy':'multi_node_trigger','coin_type_note':'All\x20Allocators\x20share\x20the\x20same\x20Allocation\x27s\x20Coin<T>','typical_allocator_count':0x3,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'multiple_unique','non_zero_threshold':![],'uses_max':![],'common_patterns':['3\x20Allocators\x20mapped\x20to\x20Machine\x20terminal\x20nodes\x20(Complete/Refund/Lost)','Each\x20Allocator\x27s\x20Guard\x20verifies\x20progress.current_node\x20==\x20<node_name>','Mutually\x20exclusive\x20Guard\x20conditions\x20(only\x20one\x20terminal\x20node\x20active\x20at\x20a\x20time)','Machine.required_allocators[]\x20describes\x20each\x20trigger_node\x20mapping'],'dependencies':['Service','Treasury','Guard','Order','Progress','Machine','Payment'],'key_constraints':['Guard\x20conditions\x20must\x20be\x20mutually\x20exclusive','Sequence-sensitive:\x20business-flow\x20order','Machine.required_allocators[trigger_node]\x20must\x20map\x20to\x20Allocator\x20indices'],'recommended_templates':[]},{'id':'allocation_standalone_periodic_split','name':'Standalone\x20periodic\x20split\x20(investment\x20dividends\x20/\x20shared\x20income)','trigger_source':'standalone','distribution_strategy':'periodic_split','coin_type_note':'Coin<T>\x20must\x20match\x20the\x20asset\x20being\x20distributed\x20(e.g.\x20profit\x20token)','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x20N\x20Rate\x20sharing\x20items,\x20sum(rates)\x20===\x2010000','Each\x20sharing.who=Entity\x20points\x20to\x20a\x20beneficiary\x20wallet\x20(not\x20Treasury)','Guard\x20verifies\x20time-based\x20trigger\x20(e.g.\x20context(Clock).timestamp\x20>=\x20next_release)\x20or\x20signer\x20authorization','User\x20calls\x20receive()\x20to\x20deposit\x20funds,\x20then\x20alloc()\x20to\x20trigger\x20distribution','No\x20Service/Order/Progress/Machine\x20context\x20required'],'dependencies':['Treasury','Guard','Payment'],'key_constraints':['F-A-05:\x20sum(rates)\x20===\x2010000\x20(pure\x20Rate\x20mode)','R-A-3-04:\x20standalone\x20mode\x20has\x20no\x20Service-layer\x20access\x20control\x20—\x20Guard\x20+\x20Passport\x20MUST\x20be\x20sufficient','Caller\x20is\x20fully\x20responsible\x20for\x20receive\x20→\x20alloc\x20lifecycle\x20(no\x20auto-trigger)','Guard\x20should\x20bind\x20Signer\x20to\x20prevent\x20unauthorized\x20alloc()\x20calls'],'recommended_templates':['T-A-09']},{'id':'allocation_standalone_vesting','name':'Standalone\x20vesting\x20release\x20(time-locked\x20multi-stage\x20unlock)','trigger_source':'standalone','distribution_strategy':'time_locked_vesting','coin_type_note':'Coin<T>\x20must\x20match\x20the\x20vested\x20asset\x20(e.g.\x20locked\x20team\x20tokens)','typical_allocator_count':0x3,'sharing_who_types':['Entity'],'modes_used':['Amount','Rate','Surplus'],'guard_requirement':'multiple_unique','non_zero_threshold':!![],'uses_max':!![],'common_patterns':['N\x20Allocators,\x20each\x20mapped\x20to\x20a\x20vesting\x20stage\x20(e.g.\x2025%\x20at\x20month\x2012,\x2025%\x20at\x20month\x2024,\x2050%\x20surplus\x20at\x20month\x2036)','Each\x20Allocator\x27s\x20Guard\x20verifies\x20context(Clock).timestamp\x20>=\x20stage_unlock_time','Amount\x20sharing\x20per\x20stage\x20with\x20max\x20field\x20capping\x20the\x20cumulative\x20release','Final\x20Allocator\x20uses\x20Surplus\x20to\x20drain\x20remaining\x20balance\x20after\x20last\x20vesting\x20stage','Mutually\x20exclusive\x20Guard\x20conditions\x20(only\x20one\x20stage\x20active\x20at\x20a\x20time,\x20based\x20on\x20timestamp)','User\x20calls\x20receive()\x20to\x20deposit\x20locked\x20tokens,\x20then\x20alloc()\x20at\x20each\x20vesting\x20milestone'],'dependencies':['Treasury','Guard','Passport','Payment'],'key_constraints':['F-A-04:\x20at\x20most\x201\x20Surplus\x20per\x20Allocator\x20(final\x20stage\x20uses\x20Surplus\x20to\x20drain\x20remainder)','F-A-08:\x20Amount\x20sum\x20<=\x20max\x20(EAMOUNT_EXCEEDS_MAX)','R-A-3-04:\x20standalone\x20mode\x20has\x20no\x20Service-layer\x20access\x20control\x20—\x20Guard\x20time-lock\x20MUST\x20be\x20enforced','Guard\x20conditions\x20must\x20be\x20mutually\x20exclusive\x20by\x20timestamp\x20(R-A-4-02)','Caller\x20must\x20wait\x20for\x20time-lock\x20expiry\x20before\x20alloc()\x20succeeds;\x20otherwise\x20alloc()\x20silently\x20returns\x20(R-A-4-01)'],'recommended_templates':['T-A-10']}];export const ALLOCATION_LEDGER_VERSION='1.0.0';export function getScenesByTriggerSource(a){return ALLOCATION_SCENES['filter'](b=>b['trigger_source']===a);}export function getScenesByMode(a){return ALLOCATION_SCENES['filter'](b=>b['modes_used']['includes'](a));}export function getScenesByStrategy(a){return ALLOCATION_SCENES['filter'](b=>b['distribution_strategy']===a);}export function findSceneById(a){return ALLOCATION_SCENES['find'](b=>b['id']===a);}export function inferSceneFromIntent(a){const b=a['toLowerCase']();if(b['includes']('arbitration')||b['includes']('fees\x20alloc'))return findSceneById('allocation_arbitration_fees');if(b['includes']('standalone')||b['includes']('periodic\x20split')||b['includes']('investment\x20dividend')||b['includes']('shared\x20income')||b['includes']('dividend'))return findSceneById('allocation_standalone_periodic_split');if(b['includes']('vesting')||b['includes']('time-lock')||b['includes']('unlock\x20period')||b['includes']('locked\x20release')||b['includes']('token\x20unlock'))return findSceneById('allocation_standalone_vesting');if(b['includes']('refund')){if(b['includes']('order')||b['includes']('100%'))return findSceneById('allocation_refund_to_order');if(b['includes']('surplus')||b['includes']('merchant'))return findSceneById('allocation_refund_first_surplus_to_merchant');}if(b['includes']('alternative')||b['includes']('priority')||b['includes']('treasury')&&b['includes']('personal'))return findSceneById('allocation_treasury_personal_alternatives');if(b['includes']('tiered')||b['includes']('threshold\x20switch'))return findSceneById('allocation_tiered_by_order_amount');if(b['includes']('dynamic\x20recipient')||b['includes']('referrer')||b['includes']('guardidentifier'))return findSceneById('allocation_dynamic_recipient');if(b['includes']('retain')||b['includes']('max'))return findSceneById('allocation_max_capped_retain');if(b['includes']('multi-node')||b['includes']('multi\x20machine')||b['includes']('multi_node'))return findSceneById('allocation_multi_node_trigger');const c=(a['match'](/%/g)||[])['length'];if(c<=0x1)return findSceneById('allocation_merchant_full_payment');if(c>=0x2)return findSceneById('allocation_standard_three_way_split');return undefined;}export function getAllScenes(){return[...ALLOCATION_SCENES];}export function getScenesCount(){return ALLOCATION_SCENES['length'];}export function allocationModeToNumber(a){switch(a){case'Amount':return ALLOCATION_MODE_AMOUNT;case'Rate':return ALLOCATION_MODE_RATE;case'Surplus':return ALLOCATION_MODE_SURPLUS;}}export function allocationModeFromNumber(a){switch(a){case ALLOCATION_MODE_AMOUNT:return'Amount';case ALLOCATION_MODE_RATE:return'Rate';case ALLOCATION_MODE_SURPLUS:return'Surplus';default:throw new Error('Invalid\x20AllocationMode\x20number:\x20'+a);}}export function getRecipientType(a){if('GuardIdentifier'in a)return'GuardIdentifier';if('Entity'in a)return'Entity';return'Signer';}export function isSignerRecipient(a){return'Signer'in a;}export function isEntityRecipient(a){return'Entity'in a;}export function isGuardIdentifierRecipient(a){return'GuardIdentifier'in a;}export function getErrorName(a){for(const [b,d]of Object['entries'](ALLOCATION_ERROR_CODES)){if(d===a)return b;}return undefined;}export function getErrorDescription(a){const b={0x1:'GuardIdentifier\x20resolved\x20value\x20is\x20not\x20an\x20address\x20type',0x2:'Allocator\x20count\x20exceeds\x20MAX_ALLOCATOR_COUNT\x20(100)',0x3:'No\x20Allocator\x20in\x20the\x20allocators\x20vector',0x4:'Pure\x20Rate\x20mode\x20sum\x20!=\x2010000\x20(no\x20Surplus\x20to\x20absorb\x20remainder)',0x5:'Multiple\x20Surplus\x20sharing\x20in\x20a\x20single\x20Allocator',0x6:'Rate\x20+\x20Surplus\x20sum\x20>\x2010000',0x7:'balance\x20<\x20threshold\x20(insufficient\x20balance\x20to\x20trigger\x20alloc)',0x8:'allocators.allocators\x20is\x20empty',0x9:'payment_info\x20is\x20None\x20when\x20alloc()\x20is\x20called',0xa:'sharing\x20count\x20exceeds\x20MAX_SHARING_COUNT\x20(100)',0xb:'sharing\x20mode\x20is\x20not\x200\x20(Amount)\x20/\x201\x20(Rate)\x20/\x202\x20(Surplus)',0xc:'Amount\x20sum\x20(fix)\x20<\x20threshold',0xd:'Amount\x20sum\x20(fix)\x20>\x20max',0xe:'distribution\x20computes\x20to\x20zero\x20while\x20the\x20pool\x20still\x20holds\x20funds\x20(or\x20balance\x20is\x200)',0xf:'GuardIdentifier\x20recipient\x20address\x20!=\x20payment_info.for_object\x20anchor\x20(abort\x20fires\x20only\x20when\x20a\x20for_object\x20binding\x20is\x20declared)'};return b[a];}
|
|
1
|
+
import{MAX_SHARING_COUNT,MAX_ALLOCATOR_COUNT}from'@wowok/wowok';export{MAX_ALLOCATOR_COUNT};export const ALLOCATION_MAX_SHARING_COUNT=MAX_SHARING_COUNT;export const ALLOCATION_MODE_AMOUNT=0x0;export const ALLOCATION_MODE_RATE=0x1;export const ALLOCATION_MODE_SURPLUS=0x2;export const ALLOCATION_MODE_RATE_GROSS=0x3;export const RATE_TOTAL_FULL=0x2710;export const ALLOCATION_ERROR_CODES={'ERECIPIENT_IDENTIFIER_NOT_ADDRESS':0x1,'EALLOCATOR_COUNT_EXCEEDED':0x2,'ENO_ALLOCATOR':0x3,'ERATE_NOT_10000':0x4,'EMULTIPLE_SURPLUS':0x5,'ERATE_EXCEEDS_10000':0x6,'EINSUFFICIENT_BALANCE':0x7,'EALLOCATORS_EMPTY':0x8,'ENO_PAYMENT_INFO':0x9,'ESHARING_COUNT_EXCEEDED':0xa,'ESHARING_MODE_INVALID':0xb,'EAMOUNT_BELOW_THRESHOLD':0xc,'EAMOUNT_EXCEEDS_MAX':0xd,'EZERO_DISTRIBUTION':0xe,'ERECIPIENT_NOT_FOR_OBJECT':0xf,'E_ONCE_TRIGGERED':0x10,'EMIXED_RATE_BASES':0x11};export const ORDER_ALLOCATION_ALREADY_SPECIFIED='E_ALLOCATION_ALREADY_SPECIFIED';export const ALLOCATION_SCENES=[{'id':'allocation_standard_three_way_split','name':'Standard\x20three-way\x20split\x20(merchant\x20/\x20platform\x20/\x20logistics)','trigger_source':'service_order_allocators','distribution_strategy':'pure_rate','coin_type_note':'All\x20three\x20Treasury\x20objects\x20must\x20use\x20the\x20same\x20Coin<T>\x20type\x20as\x20the\x20Allocation','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x203\x20Rate\x20sharing\x20items,\x20sum(rates)\x20===\x2010000','Each\x20sharing.who=Entity\x20points\x20to\x20a\x20Treasury\x20address','Guard\x20verifies\x20order.service\x20binding\x20(query\x201563)\x20to\x20prevent\x20cross-project\x20bypass','Guard\x20verifies\x20progress.current_node\x20===\x20\x27Complete\x27'],'dependencies':['Service','Treasury','Guard','Order','Progress','Machine','Payment'],'key_constraints':['F-A-05:\x20sum(rates)\x20===\x2010000\x20(pure\x20Rate\x20mode)','Treasury\x20Permission\x20should\x20match\x20Service\x20Permission\x20(R-A-12)','order_allocators\x20immutable\x20after\x20Service\x20publish\x20(R-A-10)'],'recommended_templates':['T-A-02']},{'id':'allocation_merchant_full_payment','name':'Merchant\x20full\x20payment\x20(single\x20recipient,\x20100%)','trigger_source':'service_order_allocators','distribution_strategy':'pure_rate','coin_type_note':'Simplest\x20configuration\x20—\x20single\x20Treasury\x20or\x20personal\x20address','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'single_relaxed','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x201\x20Rate\x20sharing\x20=\x2010000','Guard\x20only\x20verifies\x20order\x20status\x20(no\x20complex\x20conditions)','who=Entity\x20can\x20be\x20either\x20Treasury\x20or\x20personal\x20wallet'],'dependencies':['Service','Guard','Order','Payment'],'key_constraints':['Simplest\x20allocation\x20configuration','No\x20multi-party\x20coordination\x20required'],'recommended_templates':['T-A-01']},{'id':'allocation_refund_first_surplus_to_merchant','name':'Refund\x20first\x20+\x20surplus\x20to\x20merchant\x20(Amount\x20+\x20Surplus\x20hybrid)','trigger_source':'service_order_allocators','distribution_strategy':'amount_plus_surplus','coin_type_note':'Refund\x20amount\x20must\x20match\x20Coin<T>\x20precision','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Amount','Surplus'],'guard_requirement':'required','non_zero_threshold':!![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x202\x20sharing\x20items','sharing[0]:\x20Amount=refund_value,\x20who=Entity(customer_address)','sharing[1]:\x20Surplus,\x20who=Entity(merchant_treasury)','fix\x20=\x20refund_value\x20(cached\x20Amount\x20sum)','threshold\x20=\x20refund_value\x20(ensure\x20sufficient\x20balance\x20for\x20Amount)'],'dependencies':['Service','Treasury','Guard','Order','Payment'],'key_constraints':['F-A-04:\x20at\x20most\x201\x20Surplus\x20per\x20Allocator','F-A-07:\x20fix\x20>=\x20threshold\x20(Amount\x20sum\x20must\x20cover\x20threshold)','fix\x20must\x20precisely\x20match\x20the\x20refund\x20amount'],'recommended_templates':['T-A-03']},{'id':'allocation_treasury_personal_alternatives','name':'Treasury\x20+\x20Personal\x20alternative\x20strategies\x20(caller-specified\x20guard)','trigger_source':'service_order_allocators','distribution_strategy':'first_match_alternatives','coin_type_note':'Both\x20target\x20addresses\x20must\x20accept\x20the\x20same\x20Coin<T>','typical_allocator_count':0x2,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'multiple_unique','non_zero_threshold':![],'uses_max':![],'common_patterns':['2\x20Allocators,\x20each\x20with\x201\x20Rate=10000\x20sharing','Allocator[0]:\x20guard=guard_treasury,\x20who=Entity(treasury_address)','Allocator[1]:\x20guard=guard_personal,\x20who=Entity(personal_address)','Two\x20Guard\x20objects\x20must\x20be\x20different\x20addresses\x20(R-A-11)','caller-specified\x20guard:\x20caller\x20selects\x20Treasury\x20or\x20Personal\x20path\x20via\x20alloc_by_guard;\x20the\x20Passport\x20hard-verifies\x20the\x20selected\x20Guard\x20(failure\x20aborts\x20with\x20E_VERIFY_FAILED;\x20caller\x20must\x20switch\x20guard\x20and\x20retry)'],'dependencies':['Service','Treasury','Guard','Order','Payment'],'key_constraints':['F-A-14:\x20allocators[].guard\x20must\x20be\x20unique','Treasury\x20Permission\x20should\x20match\x20Service\x20Permission\x20(R-A-12)','Guard\x20A\x20and\x20Guard\x20B\x20may\x20share\x20root/table\x20but\x20must\x20differ\x20in\x20description'],'recommended_templates':['T-A-04']},{'id':'allocation_tiered_by_order_amount','name':'Tiered\x20split\x20by\x20order\x20amount\x20(multi-Allocator\x20amount-threshold\x20switch)','trigger_source':'service_order_allocators','distribution_strategy':'tiered_by_amount','coin_type_note':'Amount\x20threshold\x20uses\x20Coin<T>\x20smallest\x20unit\x20(e.g.\x20MIST\x20for\x20WOW)','typical_allocator_count':0x2,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'multiple_unique','non_zero_threshold':![],'uses_max':![],'common_patterns':['2\x20Allocators\x20triggered\x20by\x20mutually\x20exclusive\x20Guard\x20conditions','Allocator[0]:\x20guard\x20verifies\x20order.amount\x20<\x20threshold,\x20Rate=10000\x20to\x20merchant','Allocator[1]:\x20guard\x20verifies\x20order.amount\x20>=\x20threshold,\x20Rate=8000/2000\x20split','caller-specified\x20guard:\x20caller\x20selects\x20the\x20matching\x20Allocator\x20based\x20on\x20order\x20amount;\x20allocator\x20order\x20is\x20irrelevant','Guard\x20queries\x20order.amount\x20(query\x201561)'],'dependencies':['Service','Treasury','Guard','Order','Payment'],'key_constraints':['Guard\x20conditions\x20must\x20be\x20mutually\x20exclusive\x20(R-A-4-02\x20design\x20clarity)','Caller\x20must\x20select\x20correct\x20guard\x20based\x20on\x20order.amount\x20(no\x20auto-fallback)'],'recommended_templates':['T-A-05']},{'id':'allocation_dynamic_recipient','name':'Multi-role\x20split\x20with\x20dynamic\x20recipient\x20(GuardIdentifier)','trigger_source':'service_order_allocators','distribution_strategy':'dynamic_recipient','coin_type_note':'Passport\x20table\x20must\x20contain\x20address-typed\x20entry\x20at\x20the\x20referenced\x20identifier','typical_allocator_count':0x1,'sharing_who_types':['Entity','GuardIdentifier'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x203\x20Rate\x20sharing\x20items','sharing[0]:\x20Rate=8000,\x20who=Entity(merchant_treasury)','sharing[1]:\x20Rate=1000,\x20who=Entity(platform_treasury)','sharing[2]:\x20Rate=1000,\x20who=GuardIdentifier(0)\x20—\x20resolves\x20from\x20Passport\x20table','Customer\x20submits\x20Passport\x20with\x20referrer\x20address\x20at\x20identifier=0'],'dependencies':['Service','Treasury','Guard','Passport','Order','Payment'],'key_constraints':['F-A-13:\x20Passport\x20table[identifier]\x20must\x20be\x20address\x20type\x20(else\x20ERECIPIENT_IDENTIFIER_NOT_ADDRESS)','Guard\x20must\x20verify\x20Passport\x20completeness','Customer\x20order\x20must\x20include\x20Passport\x20with\x20referrer\x20address'],'recommended_templates':['T-A-06']},{'id':'allocation_arbitration_fees','name':'Arbitration\x20fees\x20split\x20(arbitrator\x20/\x20platform)','trigger_source':'arbitration_fees','distribution_strategy':'pure_rate','coin_type_note':'Coin<T>\x20must\x20match\x20Arbitration\x27s\x20fee\x20Coin\x20type','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Triggered\x20by\x20the\x20Arbitration\x20fee-allocation\x20operation\x20(permission\x20365),\x20direct\x20or\x20Passport\x20path','Single\x20Allocator,\x202\x20Rate\x20sharing\x20items:\x208000\x20arbitrator\x20/\x202000\x20platform','payment_info\x20reuses\x20Arbitration\x27s\x20payment_info','Caller\x20must\x20hold\x20ARBITRATION_FEES_ALLOC=365\x20permission'],'dependencies':['Arbitration','Treasury','Guard','Payment'],'key_constraints':['Independent\x20from\x20Service-order\x20Allocation','Requires\x20ARBITRATION_FEES_ALLOC=365\x20permission'],'recommended_templates':['T-A-08']},{'id':'allocation_refund_to_order','name':'Refund\x20Allocator\x20(100%\x20to\x20Order\x20object)','trigger_source':'service_order_allocators','distribution_strategy':'refund_to_order','coin_type_note':'who=Entity\x20must\x20be\x20the\x20Order\x20object\x20address\x20(NOT\x20a\x20personal\x20wallet)','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x201\x20Rate=10000\x20sharing','who=Entity(order_address)\x20—\x20funds\x20flow\x20back\x20to\x20Order,\x20not\x20personal\x20wallet','Guard\x20verifies\x20customer\x20refund\x20request\x20and\x20eligibility','Customer-side\x20risk\x20assessment\x20adds\x208-point\x20weight\x20(onchain_topology\x20graph\x20evaluation)'],'dependencies':['Service','Guard','Order','Payment'],'key_constraints':['who=Entity\x20MUST\x20be\x20Order\x20object\x20address\x20(not\x20personal\x20address)','Customer\x20due-diligence\x20rewards\x20this\x20configuration\x20(8-point\x20weight)','Refund\x20funds\x20return\x20to\x20Order\x20for\x20downstream\x20handling'],'recommended_templates':['T-A-07']},{'id':'allocation_max_capped_retain','name':'Max-capped\x20allocation\x20(retain\x20residual\x20balance)','trigger_source':'service_order_allocators','distribution_strategy':'max_capped','coin_type_note':'max\x20field\x20uses\x20Coin<T>\x20smallest\x20unit','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Amount','Rate'],'guard_requirement':'required','non_zero_threshold':!![],'uses_max':!![],'common_patterns':['Single\x20Allocator\x20with\x20max\x20field\x20set','max\x20triple\x20role:\x20Amount\x20cap\x20+\x20NET\x20Rate\x20base\x20+\x20Surplus\x20cap','Amount\x20sharing\x20consumes\x20fix;\x20NET\x20Rate\x20sharing\x20uses\x20(max\x20-\x20fix)\x20as\x20base\x20(RateGross\x20uses\x20max\x20itself)','Residual\x20balance\x20remains\x20in\x20Allocation\x20for\x20subsequent\x20alloc()\x20calls'],'dependencies':['Service','Treasury','Guard','Order','Payment'],'key_constraints':['F-A-08:\x20Amount\x20sum\x20<=\x20max\x20(EAMOUNT_EXCEEDS_MAX)','NET\x20Rate:\x20max\x20-\x20fix\x20becomes\x20the\x20base\x20(NOT\x20balance\x20-\x20fix);\x20RateGross:\x20the\x20base\x20is\x20max\x20(fix\x20not\x20removed)','Residual\x20balance\x20may\x20be\x20claimed\x20by\x20re-triggering\x20alloc()'],'recommended_templates':[]},{'id':'allocation_multi_node_trigger','name':'Multi-Machine-node\x20triggered\x20allocation\x20(Complete\x20/\x20Refund\x20/\x20Lost)','trigger_source':'service_order_allocators','distribution_strategy':'multi_node_trigger','coin_type_note':'All\x20Allocators\x20share\x20the\x20same\x20Allocation\x27s\x20Coin<T>','typical_allocator_count':0x3,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'multiple_unique','non_zero_threshold':![],'uses_max':![],'common_patterns':['3\x20Allocators\x20mapped\x20to\x20Machine\x20terminal\x20nodes\x20(Complete/Refund/Lost)','Each\x20Allocator\x27s\x20Guard\x20verifies\x20progress.current_node\x20==\x20<node_name>','Mutually\x20exclusive\x20Guard\x20conditions\x20(only\x20one\x20terminal\x20node\x20active\x20at\x20a\x20time)','Machine.required_allocators[]\x20describes\x20each\x20trigger_node\x20mapping'],'dependencies':['Service','Treasury','Guard','Order','Progress','Machine','Payment'],'key_constraints':['Guard\x20conditions\x20must\x20be\x20mutually\x20exclusive','Sequence-sensitive:\x20business-flow\x20order','Machine.required_allocators[trigger_node]\x20must\x20map\x20to\x20Allocator\x20indices'],'recommended_templates':[]},{'id':'allocation_standalone_periodic_split','name':'Standalone\x20periodic\x20split\x20(investment\x20dividends\x20/\x20shared\x20income)','trigger_source':'standalone','distribution_strategy':'periodic_split','coin_type_note':'Coin<T>\x20must\x20match\x20the\x20asset\x20being\x20distributed\x20(e.g.\x20profit\x20token)','typical_allocator_count':0x1,'sharing_who_types':['Entity'],'modes_used':['Rate'],'guard_requirement':'required','non_zero_threshold':![],'uses_max':![],'common_patterns':['Single\x20Allocator,\x20N\x20Rate\x20sharing\x20items,\x20sum(rates)\x20===\x2010000','Each\x20sharing.who=Entity\x20points\x20to\x20a\x20beneficiary\x20wallet\x20(not\x20Treasury)','Guard\x20verifies\x20time-based\x20trigger\x20(e.g.\x20context(Clock).timestamp\x20>=\x20next_release)\x20or\x20signer\x20authorization','User\x20calls\x20receive()\x20to\x20deposit\x20funds,\x20then\x20alloc()\x20to\x20trigger\x20distribution','No\x20Service/Order/Progress/Machine\x20context\x20required'],'dependencies':['Treasury','Guard','Payment'],'key_constraints':['F-A-05:\x20sum(rates)\x20===\x2010000\x20(pure\x20Rate\x20mode)','R-A-3-04:\x20standalone\x20mode\x20has\x20no\x20Service-layer\x20access\x20control\x20—\x20Guard\x20+\x20Passport\x20MUST\x20be\x20sufficient','Caller\x20is\x20fully\x20responsible\x20for\x20receive\x20→\x20alloc\x20lifecycle\x20(no\x20auto-trigger)','Guard\x20should\x20bind\x20Signer\x20to\x20prevent\x20unauthorized\x20alloc()\x20calls'],'recommended_templates':['T-A-09']},{'id':'allocation_standalone_vesting','name':'Standalone\x20vesting\x20release\x20(time-locked\x20multi-stage\x20unlock)','trigger_source':'standalone','distribution_strategy':'time_locked_vesting','coin_type_note':'Coin<T>\x20must\x20match\x20the\x20vested\x20asset\x20(e.g.\x20locked\x20team\x20tokens)','typical_allocator_count':0x3,'sharing_who_types':['Entity'],'modes_used':['Amount','Rate','Surplus'],'guard_requirement':'multiple_unique','non_zero_threshold':!![],'uses_max':!![],'common_patterns':['N\x20Allocators,\x20each\x20mapped\x20to\x20a\x20vesting\x20stage\x20(e.g.\x2025%\x20at\x20month\x2012,\x2025%\x20at\x20month\x2024,\x2050%\x20surplus\x20at\x20month\x2036)','Each\x20Allocator\x27s\x20Guard\x20verifies\x20context(Clock).timestamp\x20>=\x20stage_unlock_time','Amount\x20sharing\x20per\x20stage\x20with\x20max\x20field\x20capping\x20the\x20cumulative\x20release','Final\x20Allocator\x20uses\x20Surplus\x20to\x20drain\x20remaining\x20balance\x20after\x20last\x20vesting\x20stage','Mutually\x20exclusive\x20Guard\x20conditions\x20(only\x20one\x20stage\x20active\x20at\x20a\x20time,\x20based\x20on\x20timestamp)','User\x20calls\x20receive()\x20to\x20deposit\x20locked\x20tokens,\x20then\x20alloc()\x20at\x20each\x20vesting\x20milestone'],'dependencies':['Treasury','Guard','Passport','Payment'],'key_constraints':['F-A-04:\x20at\x20most\x201\x20Surplus\x20per\x20Allocator\x20(final\x20stage\x20uses\x20Surplus\x20to\x20drain\x20remainder)','F-A-08:\x20Amount\x20sum\x20<=\x20max\x20(EAMOUNT_EXCEEDS_MAX)','R-A-3-04:\x20standalone\x20mode\x20has\x20no\x20Service-layer\x20access\x20control\x20—\x20Guard\x20time-lock\x20MUST\x20be\x20enforced','Guard\x20conditions\x20must\x20be\x20mutually\x20exclusive\x20by\x20timestamp\x20(R-A-4-02)','Caller\x20must\x20wait\x20for\x20time-lock\x20expiry\x20before\x20alloc()\x20succeeds;\x20otherwise\x20alloc()\x20silently\x20returns\x20(R-A-4-01)'],'recommended_templates':['T-A-10']}];export const ALLOCATION_LEDGER_VERSION='1.0.0';export function getScenesByTriggerSource(a){return ALLOCATION_SCENES['filter'](b=>b['trigger_source']===a);}export function getScenesByMode(a){return ALLOCATION_SCENES['filter'](b=>b['modes_used']['includes'](a));}export function getScenesByStrategy(a){return ALLOCATION_SCENES['filter'](b=>b['distribution_strategy']===a);}export function findSceneById(a){return ALLOCATION_SCENES['find'](b=>b['id']===a);}export function inferSceneFromIntent(a){const b=a['toLowerCase']();if(b['includes']('arbitration')||b['includes']('fees\x20alloc'))return findSceneById('allocation_arbitration_fees');if(b['includes']('standalone')||b['includes']('periodic\x20split')||b['includes']('investment\x20dividend')||b['includes']('shared\x20income')||b['includes']('dividend'))return findSceneById('allocation_standalone_periodic_split');if(b['includes']('vesting')||b['includes']('time-lock')||b['includes']('unlock\x20period')||b['includes']('locked\x20release')||b['includes']('token\x20unlock'))return findSceneById('allocation_standalone_vesting');if(b['includes']('refund')){if(b['includes']('order')||b['includes']('100%'))return findSceneById('allocation_refund_to_order');if(b['includes']('surplus')||b['includes']('merchant'))return findSceneById('allocation_refund_first_surplus_to_merchant');}if(b['includes']('alternative')||b['includes']('priority')||b['includes']('treasury')&&b['includes']('personal'))return findSceneById('allocation_treasury_personal_alternatives');if(b['includes']('tiered')||b['includes']('threshold\x20switch'))return findSceneById('allocation_tiered_by_order_amount');if(b['includes']('dynamic\x20recipient')||b['includes']('referrer')||b['includes']('guardidentifier'))return findSceneById('allocation_dynamic_recipient');if(b['includes']('retain')||b['includes']('max'))return findSceneById('allocation_max_capped_retain');if(b['includes']('multi-node')||b['includes']('multi\x20machine')||b['includes']('multi_node'))return findSceneById('allocation_multi_node_trigger');const c=(a['match'](/%/g)||[])['length'];if(c<=0x1)return findSceneById('allocation_merchant_full_payment');if(c>=0x2)return findSceneById('allocation_standard_three_way_split');return undefined;}export function getAllScenes(){return[...ALLOCATION_SCENES];}export function getScenesCount(){return ALLOCATION_SCENES['length'];}export function allocationModeToNumber(a){switch(a){case'Amount':return ALLOCATION_MODE_AMOUNT;case'Rate':return ALLOCATION_MODE_RATE;case'Surplus':return ALLOCATION_MODE_SURPLUS;case'RateGross':return ALLOCATION_MODE_RATE_GROSS;}}export function allocationModeFromNumber(a){switch(a){case ALLOCATION_MODE_AMOUNT:return'Amount';case ALLOCATION_MODE_RATE:return'Rate';case ALLOCATION_MODE_SURPLUS:return'Surplus';case ALLOCATION_MODE_RATE_GROSS:return'RateGross';default:throw new Error('Invalid\x20AllocationMode\x20number:\x20'+a);}}export function getRecipientType(a){if('GuardIdentifier'in a)return'GuardIdentifier';if('Entity'in a)return'Entity';return'Signer';}export function isSignerRecipient(a){return'Signer'in a;}export function isEntityRecipient(a){return'Entity'in a;}export function isGuardIdentifierRecipient(a){return'GuardIdentifier'in a;}export function getErrorName(a){for(const [b,d]of Object['entries'](ALLOCATION_ERROR_CODES)){if(d===a)return b;}return undefined;}export function getErrorDescription(a){const b={0x1:'GuardIdentifier\x20resolved\x20value\x20is\x20not\x20an\x20address\x20type',0x2:'Allocator\x20count\x20exceeds\x20MAX_ALLOCATOR_COUNT\x20(100)',0x3:'No\x20Allocator\x20in\x20the\x20allocators\x20vector',0x4:'Pure\x20Rate\x20mode\x20sum\x20!=\x2010000\x20(no\x20Surplus\x20to\x20absorb\x20remainder)',0x5:'Multiple\x20Surplus\x20sharing\x20in\x20a\x20single\x20Allocator',0x6:'Rate\x20+\x20Surplus\x20sum\x20>\x2010000',0x7:'balance\x20<\x20threshold\x20(insufficient\x20balance\x20to\x20trigger\x20alloc)',0x8:'allocators.allocators\x20is\x20empty',0x9:'payment_info\x20is\x20None\x20when\x20alloc()\x20is\x20called',0xa:'sharing\x20count\x20exceeds\x20MAX_SHARING_COUNT\x20(100)',0xb:'sharing\x20mode\x20is\x20not\x200\x20(Amount)\x20/\x201\x20(Rate)\x20/\x202\x20(Surplus)\x20/\x203\x20(RateGross)',0xc:'Amount\x20sum\x20(fix)\x20<\x20threshold',0xd:'Amount\x20sum\x20(fix)\x20>\x20max',0xe:'distribution\x20computes\x20to\x20zero\x20while\x20the\x20pool\x20still\x20holds\x20funds\x20(or\x20balance\x20is\x200)',0xf:'GuardIdentifier\x20recipient\x20address\x20!=\x20payment_info.for_object\x20anchor\x20(abort\x20fires\x20only\x20when\x20a\x20for_object\x20binding\x20is\x20declared)',0x10:'once-trigger\x20key\x20already\x20consumed\x20—\x20the\x20guard\x20submitted\x20the\x20reserved\x20identifier\x20255\x20and\x20its\x20raw\x20submission\x20bytes\x20were\x20recorded\x20as\x20a\x20(guard,\x20allocator\x20index,\x20raw\x20bytes)\x20dynamic-field\x20key\x20on\x20this\x20Allocation',0x11:'mixed\x20rate\x20bases\x20—\x20one\x20allocator\x20carries\x20both\x20NET\x20Rate\x20and\x20RateGross\x20entries\x20while\x20a\x20fixed\x20Amount\x20total\x20is\x20present\x20(rejected\x20only\x20when\x20fix\x20>\x200;\x20with\x20fix\x20==\x200\x20the\x20two\x20bases\x20coincide\x20and\x20mixing\x20is\x20allowed)'};return b[a];}
|
|
@@ -97,6 +97,8 @@ export interface AllocationConstraintChecklist {
|
|
|
97
97
|
F_A_13_guard_identifier_is_address: boolean;
|
|
98
98
|
F_A_14_guard_addresses_unique: boolean;
|
|
99
99
|
F_A_15_order_allocators_immutable_after_publish: boolean;
|
|
100
|
+
F_A_16_rate_gross_sum_le_10000: boolean;
|
|
101
|
+
F_A_17_no_mixed_rate_bases: boolean;
|
|
100
102
|
}
|
|
101
103
|
export type AllocationPuzzleDimension = "A" | "B" | "C" | "D" | "E" | "F";
|
|
102
104
|
export interface AllocationPuzzle {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MAX_ALLOCATOR_COUNT,ALLOCATION_MAX_SHARING_COUNT,RATE_TOTAL_FULL}from'./allocation-ledger.js';export function initPuzzleFromIntent(a){const b={};return(a['action']||a['distribution_goal']||a['trigger_condition'])&&(b['intent']={'action':a['action']??'create','host_context':a['host_context']??'service_order_allocators','trigger_condition':a['trigger_condition']??'','distribution_goal':a['distribution_goal']??'','failure_conditions':a['failure_conditions']??[]}),b['constraints']={'F_A_01_allocator_count_le_100':!![],'F_A_02_sharing_count_le_100':!![],'F_A_03_sharing_mode_valid':!![],'F_A_04_at_most_1_surplus_per_allocator':!![],'F_A_05_pure_rate_sum_eq_10000':!![],'F_A_06_rate_plus_surplus_sum_le_10000':!![],'F_A_07_amount_sum_ge_threshold':!![],'F_A_08_amount_sum_le_max':!![],'F_A_09_balance_ge_threshold_at_alloc':!![],'F_A_10_payment_info_present':!![],'F_A_11_allocators_not_empty':!![],'F_A_12_order_at_most_1_allocation':!![],'F_A_13_guard_identifier_is_address':!![],'F_A_14_guard_addresses_unique':!![],'F_A_15_order_allocators_immutable_after_publish':!![]},b;}export function checkPuzzleCompleteness(a){const b=[],c=[];if(!a['intent'])b['push']('A'),c['push']({'dimension':'A','reason':'Intent\x20not\x20specified\x20(action\x20+\x20distribution_goal)'});else{if(!a['intent']['distribution_goal'])b['push']('A'),c['push']({'dimension':'A','reason':'distribution_goal\x20is\x20empty'});else!a['intent']['host_context']&&(b['push']('A'),c['push']({'dimension':'A','reason':'host_context\x20(trigger\x20source)\x20must\x20be\x20specified'}));}if(!a['binding'])b['push']('B'),c['push']({'dimension':'B','reason':'Binding\x20not\x20specified\x20(coin_type\x20+\x20guard_objects)'});else{if(!a['binding']['coin_type'])b['push']('B'),c['push']({'dimension':'B','reason':'coin_type\x20is\x20missing'});else a['binding']['guard_objects']['length']===0x0&&(b['push']('B'),c['push']({'dimension':'B','reason':'guard_objects\x20list\x20is\x20empty\x20—\x20at\x20least\x201\x20Guard\x20required'}));}if(!a['data_source']&&a['intent']?.['action']==='create')b['push']('C'),c['push']({'dimension':'C','reason':'Data\x20source\x20not\x20specified\x20(allocators_config\x20+\x20payment_info)'});else a['data_source']&&a['data_source']['allocators_config']['allocators']['length']===0x0&&(b['push']('C'),c['push']({'dimension':'C','reason':'allocators_config.allocators\x20is\x20empty'}));return!a['operations']&&(b['push']('D'),c['push']({'dimension':'D','reason':'Operations\x20not\x20enumerated'})),!a['logic']&&(b['push']('E'),c['push']({'dimension':'E','reason':'Logic\x20flow\x20(7-step\x20alloc)\x20not\x20defined'})),!a['constraints']&&(b['push']('F'),c['push']({'dimension':'F','reason':'Constraints\x20not\x20checked'})),{'dimensions':['A','B','C','D','E','F'],'missing':b,'missing_details':c,'complete':b['length']===0x0,'next_step':b['length']===0x0?'Puzzle\x20complete\x20—\x20ready\x20for\x20confirmation\x20text\x20generation':'Next:\x20complete\x20dimension\x20'+b[0x0]+'\x20—\x20'+c[0x0]['reason']};}export function validateConstraints(a){const b=[];if(!a['data_source'])return b;const c=a['data_source']['allocators_config'];c['allocators']['length']>MAX_ALLOCATOR_COUNT&&b['push']({'constraint_id':'F-A-01','severity':'critical','message':'Allocator\x20count\x20'+c['allocators']['length']+'\x20exceeds\x20MAX_ALLOCATOR_COUNT\x20'+MAX_ALLOCATOR_COUNT,'current_value':c['allocators']['length'],'limit':MAX_ALLOCATOR_COUNT,'related_move_error':'EALLOCATOR_COUNT_EXCEEDED\x20(2)'});c['allocators']['length']===0x0&&b['push']({'constraint_id':'F-A-11','severity':'critical','message':'allocators.allocators\x20is\x20empty\x20—\x20at\x20least\x201\x20Allocator\x20required','related_move_error':'EALLOCATORS_EMPTY\x20(8)\x20/\x20ENO_ALLOCATOR\x20(3)'});const d=c['allocators']['map'](f=>f['guard']),e=new Set(d);e['size']!==d['length']&&b['push']({'constraint_id':'F-A-14','severity':'medium','message':'Duplicate\x20Guard\x20addresses\x20in\x20allocators\x20('+d['length']+'\x20entries,\x20'+e['size']+'\x20unique)\x20—\x20alloc_by_guard\x20address\x20match\x20only\x20hits\x20the\x20first,\x20subsequent\x20duplicate\x20Allocators\x20are\x20never\x20reachable'});for(const f of c['allocators']){f['sharing']['length']>ALLOCATION_MAX_SHARING_COUNT&&b['push']({'constraint_id':'F-A-02','severity':'critical','message':'Allocator\x20'+f['guard']+'\x20has\x20'+f['sharing']['length']+'\x20sharing\x20entries,\x20exceeds\x20MAX_SHARING_COUNT\x20'+ALLOCATION_MAX_SHARING_COUNT,'current_value':f['sharing']['length'],'limit':ALLOCATION_MAX_SHARING_COUNT,'related_move_error':'ESHARING_COUNT_EXCEEDED\x20(10)'});for(const m of f['sharing']){!['Amount','Rate','Surplus']['includes'](m['mode'])&&b['push']({'constraint_id':'F-A-03','severity':'critical','message':'Invalid\x20sharing\x20mode:\x20'+m['mode'],'related_move_error':'ESHARING_MODE_INVALID\x20(11)'});}const g=f['sharing']['filter'](n=>n['mode']==='Surplus')['length'];g>0x1&&b['push']({'constraint_id':'F-A-04','severity':'high','message':'Allocator\x20'+f['guard']+'\x20has\x20'+g+'\x20Surplus\x20sharing\x20—\x20at\x20most\x201\x20allowed','current_value':g,'limit':0x1,'related_move_error':'EMULTIPLE_SURPLUS\x20(5)'});const h=f['sharing']['filter'](n=>n['mode']==='Rate')['reduce']((n,o)=>n+Number(o['sharing']),0x0),i=g>0x0;!i&&h>0x0&&h!==RATE_TOTAL_FULL&&b['push']({'constraint_id':'F-A-05','severity':'high','message':'Pure\x20Rate\x20mode\x20(no\x20Surplus)\x20sum\x20'+h+'\x20!=\x20'+RATE_TOTAL_FULL,'current_value':h,'limit':RATE_TOTAL_FULL,'related_move_error':'ERATE_NOT_10000\x20(4)'});i&&h>RATE_TOTAL_FULL&&b['push']({'constraint_id':'F-A-06','severity':'high','message':'Rate\x20+\x20Surplus\x20mode\x20sum\x20'+h+'\x20>\x20'+RATE_TOTAL_FULL,'current_value':h,'limit':RATE_TOTAL_FULL,'related_move_error':'ERATE_EXCEEDS_10000\x20(6)'});const j=f['sharing']['filter'](n=>n['mode']==='Amount')['reduce']((n,o)=>n+Number(o['sharing']),0x0),k=Number(c['threshold']);j>0x0&&j<k&&b['push']({'constraint_id':'F-A-07','severity':'high','message':'Amount\x20sum\x20'+j+'\x20<\x20threshold\x20'+k,'current_value':j,'limit':k,'related_move_error':'EAMOUNT_BELOW_THRESHOLD\x20(12)'});f['max']!=null&&j>Number(f['max'])&&b['push']({'constraint_id':'F-A-08','severity':'medium','message':'Amount\x20sum\x20'+j+'\x20>\x20max\x20'+Number(f['max']),'current_value':j,'limit':Number(f['max']),'related_move_error':'EAMOUNT_EXCEEDS_MAX\x20(13)'});const l=f['sharing']['find'](n=>typeof n['who']==='object'&&'GuardIdentifier'in n['who']);if(l){}}return b;}export function generateConfirmationText(a){const b=[];b['push']('═══\x20Allocation\x20Confirmation\x20═══'),b['push']('');if(a['intent']){b['push']('Action:\x20'+a['intent']['action']),b['push']('Host\x20context:\x20'+a['intent']['host_context']),b['push']('Trigger:\x20'+a['intent']['trigger_condition']),b['push']('Distribution\x20goal:\x20'+a['intent']['distribution_goal']);if(a['intent']['failure_conditions']['length']>0x0){b['push']('Failure\x20conditions:');for(const d of a['intent']['failure_conditions'])b['push']('\x20\x20-\x20'+d);}b['push']('');}if(a['binding']){b['push']('─\x20Binding\x20──────────────'),b['push']('Coin\x20type:\x20'+a['binding']['coin_type']);if(a['binding']['host_service'])b['push']('Host\x20Service:\x20'+a['binding']['host_service']);if(a['binding']['host_arbitration'])b['push']('Host\x20Arbitration:\x20'+a['binding']['host_arbitration']);if(a['binding']['bound_order'])b['push']('Bound\x20Order:\x20'+a['binding']['bound_order']);if(a['binding']['trigger_node'])b['push']('Trigger\x20node:\x20'+a['binding']['trigger_node']);b['push']('Guard\x20objects\x20('+a['binding']['guard_objects']['length']+'):\x20'+a['binding']['guard_objects']['join'](',\x20')),b['push']('Payment\x20info\x20source:\x20'+a['binding']['payment_info_source']),b['push']('');}if(a['data_source']){const e=a['data_source']['allocators_config'];b['push']('─\x20Data\x20Source\x20──────────────'),b['push']('Description:\x20'+e['description']),b['push']('Threshold:\x20'+e['threshold']),b['push']('Allocators:\x20'+e['allocators']['length']),e['allocators']['forEach']((f,g)=>{b['push']('\x20\x20['+g+']\x20guard='+f['guard']+',\x20sharing='+f['sharing']['length']+'\x20items,\x20fix='+(f['fix']??'0')+',\x20max='+(f['max']??'null')),f['sharing']['forEach']((h,k)=>{b['push']('\x20\x20\x20\x20\x20\x20('+k+')\x20who='+JSON['stringify'](h['who'])+',\x20sharing='+h['sharing']+',\x20mode='+h['mode']);});}),b['push']('Payment\x20info\x20for_object:\x20'+a['data_source']['payment_info']['for_object']+(a['data_source']['payment_info']['for_object']?'\x20(ENFORCED\x20at\x20alloc:\x20GuardIdentifier\x20submissions\x20must\x20equal\x20this\x20address,\x20abort\x2015\x20on\x20mismatch)':'\x20(no\x20anchor:\x20nothing\x20enforced\x20on-chain,\x20recipient\x20routing\x20is\x20the\x20creator\x27s\x20business)')),b['push']('Coin\x20source:\x20'+a['data_source']['coin_source']),b['push']('');}if(a['logic']){b['push']('─\x20Logic\x20──────────────'),b['push']('Guard\x20matching:\x20'+a['logic']['guard_matching_strategy']),b['push']('alloc()\x20flow\x20('+a['logic']['alloc_flow']['length']+'\x20steps):');for(const f of a['logic']['alloc_flow']){b['push']('\x20\x20'+f['step']+'.\x20'+f['action']+':\x20'+f['description']);}b['push']('');}const c=validateConstraints(a);if(c['length']>0x0){b['push']('─\x20Constraint\x20Violations\x20──────────────');for(const g of c){b['push']('\x20\x20['+g['severity']+']\x20'+g['constraint_id']+':\x20'+g['message']);}b['push']('');}return b['join']('\x0a');}export function buildDefaultAllocFlow(){return[{'step':0x1,'action':'pre_check','description':'assert\x20balance\x20>=\x20threshold,\x20payment_info.is_some(),\x20allocators\x20not\x20empty'},{'step':0x2,'action':'guard_lookup','description':'iterate\x20allocators[],\x20locate\x20alloc.guard\x20==\x20alloc_by_guard\x20address;\x20on\x20hit\x20run\x20the\x20Passport\x20guard-result\x20hard\x20verification\x20(failure\x20aborts\x20E_VERIFY_FAILED)'},{'step':0x3,'action':'rate_base_calc','description':'total_rates\x20=\x20max\x20-\x20fix\x20(if\x20max)\x20else\x20balance\x20-\x20fix'},{'step':0x4,'action':'sharing_distribution','description':'iterate\x20sharing[],\x20split\x20by\x20mode\x20(Amount/Rate/Surplus\x20placeholder)'},{'step':0x5,'action':'surplus_distribution','description':'withdraw_all\x20to\x20surplus_recipient\x20(if\x20any)'},{'step':0x6,'action':'recipient_resolution','description':'resolve\x20address\x20from\x20GuardIdentifier(passport)\x20/\x20Entity(static)\x20/\x20Signer(tx\x20sender);\x20GuardIdentifier\x20submissions\x20are\x20additionally\x20checked\x20against\x20payment_info.for_object\x20when\x20it\x20is\x20Some\x20(mismatch\x20aborts\x20ERECIPIENT_NOT_FOR_OBJECT\x2015;\x20None\x20=\x20no\x20anchor,\x20nothing\x20enforced)'},{'step':0x7,'action':'payment_creation','description':'create\x20Payment\x20object,\x20push\x20to\x20self.payment\x20vector'}];}export function buildDefaultRecipientRules(){return[{'recipient_type':'GuardIdentifier','resolution_source':'passport_table','safety_level':'safe'},{'recipient_type':'Entity','resolution_source':'static_address','safety_level':'safe'},{'recipient_type':'Signer','resolution_source':'tx_sender','safety_level':'dangerous'}];}export function buildDefaultLogicPuzzle(){return{'alloc_flow':buildDefaultAllocFlow(),'guard_matching_strategy':'caller_specified_guard','recipient_resolution_rules':buildDefaultRecipientRules()};}export const ALLOCATION_PUZZLE_VERSION='1.0.0';
|
|
1
|
+
import{MAX_ALLOCATOR_COUNT,ALLOCATION_MAX_SHARING_COUNT,RATE_TOTAL_FULL}from'./allocation-ledger.js';export function initPuzzleFromIntent(a){const b={};return(a['action']||a['distribution_goal']||a['trigger_condition'])&&(b['intent']={'action':a['action']??'create','host_context':a['host_context']??'service_order_allocators','trigger_condition':a['trigger_condition']??'','distribution_goal':a['distribution_goal']??'','failure_conditions':a['failure_conditions']??[]}),b['constraints']={'F_A_01_allocator_count_le_100':!![],'F_A_02_sharing_count_le_100':!![],'F_A_03_sharing_mode_valid':!![],'F_A_04_at_most_1_surplus_per_allocator':!![],'F_A_05_pure_rate_sum_eq_10000':!![],'F_A_06_rate_plus_surplus_sum_le_10000':!![],'F_A_07_amount_sum_ge_threshold':!![],'F_A_08_amount_sum_le_max':!![],'F_A_09_balance_ge_threshold_at_alloc':!![],'F_A_10_payment_info_present':!![],'F_A_11_allocators_not_empty':!![],'F_A_12_order_at_most_1_allocation':!![],'F_A_13_guard_identifier_is_address':!![],'F_A_14_guard_addresses_unique':!![],'F_A_15_order_allocators_immutable_after_publish':!![],'F_A_16_rate_gross_sum_le_10000':!![],'F_A_17_no_mixed_rate_bases':!![]},b;}export function checkPuzzleCompleteness(a){const b=[],c=[];if(!a['intent'])b['push']('A'),c['push']({'dimension':'A','reason':'Intent\x20not\x20specified\x20(action\x20+\x20distribution_goal)'});else{if(!a['intent']['distribution_goal'])b['push']('A'),c['push']({'dimension':'A','reason':'distribution_goal\x20is\x20empty'});else!a['intent']['host_context']&&(b['push']('A'),c['push']({'dimension':'A','reason':'host_context\x20(trigger\x20source)\x20must\x20be\x20specified'}));}if(!a['binding'])b['push']('B'),c['push']({'dimension':'B','reason':'Binding\x20not\x20specified\x20(coin_type\x20+\x20guard_objects)'});else{if(!a['binding']['coin_type'])b['push']('B'),c['push']({'dimension':'B','reason':'coin_type\x20is\x20missing'});else a['binding']['guard_objects']['length']===0x0&&(b['push']('B'),c['push']({'dimension':'B','reason':'guard_objects\x20list\x20is\x20empty\x20—\x20at\x20least\x201\x20Guard\x20required'}));}if(!a['data_source']&&a['intent']?.['action']==='create')b['push']('C'),c['push']({'dimension':'C','reason':'Data\x20source\x20not\x20specified\x20(allocators_config\x20+\x20payment_info)'});else a['data_source']&&a['data_source']['allocators_config']['allocators']['length']===0x0&&(b['push']('C'),c['push']({'dimension':'C','reason':'allocators_config.allocators\x20is\x20empty'}));return!a['operations']&&(b['push']('D'),c['push']({'dimension':'D','reason':'Operations\x20not\x20enumerated'})),!a['logic']&&(b['push']('E'),c['push']({'dimension':'E','reason':'Logic\x20flow\x20(7-step\x20alloc)\x20not\x20defined'})),!a['constraints']&&(b['push']('F'),c['push']({'dimension':'F','reason':'Constraints\x20not\x20checked'})),{'dimensions':['A','B','C','D','E','F'],'missing':b,'missing_details':c,'complete':b['length']===0x0,'next_step':b['length']===0x0?'Puzzle\x20complete\x20—\x20ready\x20for\x20confirmation\x20text\x20generation':'Next:\x20complete\x20dimension\x20'+b[0x0]+'\x20—\x20'+c[0x0]['reason']};}export function validateConstraints(a){const b=[];if(!a['data_source'])return b;const c=a['data_source']['allocators_config'];c['allocators']['length']>MAX_ALLOCATOR_COUNT&&b['push']({'constraint_id':'F-A-01','severity':'critical','message':'Allocator\x20count\x20'+c['allocators']['length']+'\x20exceeds\x20MAX_ALLOCATOR_COUNT\x20'+MAX_ALLOCATOR_COUNT,'current_value':c['allocators']['length'],'limit':MAX_ALLOCATOR_COUNT,'related_move_error':'EALLOCATOR_COUNT_EXCEEDED\x20(2)'});c['allocators']['length']===0x0&&b['push']({'constraint_id':'F-A-11','severity':'critical','message':'allocators.allocators\x20is\x20empty\x20—\x20at\x20least\x201\x20Allocator\x20required','related_move_error':'EALLOCATORS_EMPTY\x20(8)\x20/\x20ENO_ALLOCATOR\x20(3)'});const d=c['allocators']['map'](f=>f['guard']),e=new Set(d);e['size']!==d['length']&&b['push']({'constraint_id':'F-A-14','severity':'medium','message':'Duplicate\x20Guard\x20addresses\x20in\x20allocators\x20('+d['length']+'\x20entries,\x20'+e['size']+'\x20unique)\x20—\x20alloc_by_guard\x20address\x20match\x20only\x20hits\x20the\x20first,\x20subsequent\x20duplicate\x20Allocators\x20are\x20never\x20reachable'});for(const f of c['allocators']){f['sharing']['length']>ALLOCATION_MAX_SHARING_COUNT&&b['push']({'constraint_id':'F-A-02','severity':'critical','message':'Allocator\x20'+f['guard']+'\x20has\x20'+f['sharing']['length']+'\x20sharing\x20entries,\x20exceeds\x20MAX_SHARING_COUNT\x20'+ALLOCATION_MAX_SHARING_COUNT,'current_value':f['sharing']['length'],'limit':ALLOCATION_MAX_SHARING_COUNT,'related_move_error':'ESHARING_COUNT_EXCEEDED\x20(10)'});for(const r of f['sharing']){!['Amount','Rate','Surplus','RateGross']['includes'](r['mode'])&&b['push']({'constraint_id':'F-A-03','severity':'critical','message':'Invalid\x20sharing\x20mode:\x20'+r['mode'],'related_move_error':'ESHARING_MODE_INVALID\x20(11)'});}const g=f['sharing']['filter'](t=>t['mode']==='Surplus')['length'];g>0x1&&b['push']({'constraint_id':'F-A-04','severity':'high','message':'Allocator\x20'+f['guard']+'\x20has\x20'+g+'\x20Surplus\x20sharing\x20—\x20at\x20most\x201\x20allowed','current_value':g,'limit':0x1,'related_move_error':'EMULTIPLE_SURPLUS\x20(5)'});const h=f['sharing']['filter'](t=>t['mode']==='Amount')['reduce']((t,u)=>t+Number(u['sharing']),0x0),i=f['sharing']['some'](t=>t['mode']==='RateGross'),j=f['sharing']['some'](t=>t['mode']==='Rate'),k=i&&h===0x0&&j,l=f['sharing']['filter'](t=>t['mode']==='Rate'||k&&t['mode']==='RateGross')['reduce']((t,u)=>t+Number(u['sharing']),0x0),n=g>0x0;!(j&&i&&h>0x0)&&(!n&&l>0x0&&l!==RATE_TOTAL_FULL&&b['push']({'constraint_id':'F-A-05','severity':'high','message':'Pure\x20Rate\x20mode\x20(no\x20Surplus)\x20sum\x20'+l+'\x20!=\x20'+RATE_TOTAL_FULL,'current_value':l,'limit':RATE_TOTAL_FULL,'related_move_error':'ERATE_NOT_10000\x20(4)'}),n&&l>RATE_TOTAL_FULL&&b['push']({'constraint_id':'F-A-06','severity':'high','message':'Rate\x20+\x20Surplus\x20mode\x20sum\x20'+l+'\x20>\x20'+RATE_TOTAL_FULL,'current_value':l,'limit':RATE_TOTAL_FULL,'related_move_error':'ERATE_EXCEEDS_10000\x20(6)'}));const o=Number(c['threshold']);h>0x0&&h<o&&b['push']({'constraint_id':'F-A-07','severity':'high','message':'Amount\x20sum\x20'+h+'\x20<\x20threshold\x20'+o,'current_value':h,'limit':o,'related_move_error':'EAMOUNT_BELOW_THRESHOLD\x20(12)'});f['max']!=null&&h>Number(f['max'])&&b['push']({'constraint_id':'F-A-08','severity':'medium','message':'Amount\x20sum\x20'+h+'\x20>\x20max\x20'+Number(f['max']),'current_value':h,'limit':Number(f['max']),'related_move_error':'EAMOUNT_EXCEEDS_MAX\x20(13)'});const p=f['sharing']['filter'](t=>t['mode']==='RateGross')['reduce']((t,u)=>t+Number(u['sharing']),0x0);if(i&&!j){if(p>RATE_TOTAL_FULL)b['push']({'constraint_id':'F-A-16','severity':'high','message':'RateGross\x20sum\x20'+p+'\x20>\x20'+RATE_TOTAL_FULL,'current_value':p,'limit':RATE_TOTAL_FULL,'related_move_error':'ERATE_EXCEEDS_10000\x20(6)'});else{if(f['max']!=null){const t=Number(f['max']);h*RATE_TOTAL_FULL+p*t>t*RATE_TOTAL_FULL&&b['push']({'constraint_id':'F-A-16','severity':'high','message':'RateGross\x20plan\x20overdraws\x20max:\x20fix\x20'+h+'×10000\x20+\x20rateSum\x20'+p+'×'+t+'\x20>\x20'+t+'×10000','related_move_error':'ERATE_EXCEEDS_10000\x20(6)'});}else h>0x0&&p>=RATE_TOTAL_FULL&&b['push']({'constraint_id':'F-A-16','severity':'high','message':'RateGross\x20sum\x20'+p+'\x20with\x20fixed\x20total\x20'+h+'\x20and\x20no\x20max\x20must\x20be\x20<\x20'+RATE_TOTAL_FULL,'current_value':p,'limit':RATE_TOTAL_FULL,'related_move_error':'ERATE_EXCEEDS_10000\x20(6)'});}}j&&i&&h>0x0&&b['push']({'constraint_id':'F-A-17','severity':'high','message':'Allocator\x20'+f['guard']+'\x20mixes\x20NET\x20Rate\x20and\x20RateGross\x20with\x20a\x20fixed\x20Amount\x20total\x20('+h+')\x20—\x20abort\x20EMIXED_RATE_BASES','related_move_error':'EMIXED_RATE_BASES\x20(17)'});const q=f['sharing']['find'](u=>typeof u['who']==='object'&&'GuardIdentifier'in u['who']);if(q){}}return b;}export function generateConfirmationText(a){const b=[];b['push']('═══\x20Allocation\x20Confirmation\x20═══'),b['push']('');if(a['intent']){b['push']('Action:\x20'+a['intent']['action']),b['push']('Host\x20context:\x20'+a['intent']['host_context']),b['push']('Trigger:\x20'+a['intent']['trigger_condition']),b['push']('Distribution\x20goal:\x20'+a['intent']['distribution_goal']);if(a['intent']['failure_conditions']['length']>0x0){b['push']('Failure\x20conditions:');for(const d of a['intent']['failure_conditions'])b['push']('\x20\x20-\x20'+d);}b['push']('');}if(a['binding']){b['push']('─\x20Binding\x20──────────────'),b['push']('Coin\x20type:\x20'+a['binding']['coin_type']);if(a['binding']['host_service'])b['push']('Host\x20Service:\x20'+a['binding']['host_service']);if(a['binding']['host_arbitration'])b['push']('Host\x20Arbitration:\x20'+a['binding']['host_arbitration']);if(a['binding']['bound_order'])b['push']('Bound\x20Order:\x20'+a['binding']['bound_order']);if(a['binding']['trigger_node'])b['push']('Trigger\x20node:\x20'+a['binding']['trigger_node']);b['push']('Guard\x20objects\x20('+a['binding']['guard_objects']['length']+'):\x20'+a['binding']['guard_objects']['join'](',\x20')),b['push']('Payment\x20info\x20source:\x20'+a['binding']['payment_info_source']),b['push']('');}if(a['data_source']){const e=a['data_source']['allocators_config'];b['push']('─\x20Data\x20Source\x20──────────────'),b['push']('Description:\x20'+e['description']),b['push']('Threshold:\x20'+e['threshold']),b['push']('Allocators:\x20'+e['allocators']['length']),e['allocators']['forEach']((f,g)=>{b['push']('\x20\x20['+g+']\x20guard='+f['guard']+',\x20sharing='+f['sharing']['length']+'\x20items,\x20fix='+(f['fix']??'0')+',\x20max='+(f['max']??'null')),f['sharing']['forEach']((h,k)=>{b['push']('\x20\x20\x20\x20\x20\x20('+k+')\x20who='+JSON['stringify'](h['who'])+',\x20sharing='+h['sharing']+',\x20mode='+h['mode']);});}),b['push']('Payment\x20info\x20for_object:\x20'+a['data_source']['payment_info']['for_object']+(a['data_source']['payment_info']['for_object']?'\x20(ENFORCED\x20at\x20alloc:\x20GuardIdentifier\x20submissions\x20must\x20equal\x20this\x20address,\x20abort\x2015\x20on\x20mismatch)':'\x20(no\x20anchor:\x20nothing\x20enforced\x20on-chain,\x20recipient\x20routing\x20is\x20the\x20creator\x27s\x20business)')),b['push']('Coin\x20source:\x20'+a['data_source']['coin_source']),b['push']('');}if(a['logic']){b['push']('─\x20Logic\x20──────────────'),b['push']('Guard\x20matching:\x20'+a['logic']['guard_matching_strategy']),b['push']('alloc()\x20flow\x20('+a['logic']['alloc_flow']['length']+'\x20steps):');for(const f of a['logic']['alloc_flow']){b['push']('\x20\x20'+f['step']+'.\x20'+f['action']+':\x20'+f['description']);}b['push']('');}const c=validateConstraints(a);if(c['length']>0x0){b['push']('─\x20Constraint\x20Violations\x20──────────────');for(const g of c){b['push']('\x20\x20['+g['severity']+']\x20'+g['constraint_id']+':\x20'+g['message']);}b['push']('');}return b['join']('\x0a');}export function buildDefaultAllocFlow(){return[{'step':0x1,'action':'pre_check','description':'assert\x20balance\x20>=\x20threshold,\x20payment_info.is_some(),\x20allocators\x20not\x20empty'},{'step':0x2,'action':'guard_lookup','description':'iterate\x20allocators[],\x20locate\x20alloc.guard\x20==\x20alloc_by_guard\x20address;\x20on\x20hit\x20run\x20the\x20Passport\x20guard-result\x20hard\x20verification\x20(failure\x20aborts\x20E_VERIFY_FAILED)'},{'step':0x3,'action':'rate_base_calc','description':'NET\x20Rate:\x20total_rates\x20=\x20max\x20-\x20fix\x20(if\x20max)\x20else\x20balance\x20-\x20fix;\x20RateGross:\x20total_rates\x20=\x20max\x20(if\x20max)\x20else\x20balance\x20(fix\x20NOT\x20removed)'},{'step':0x4,'action':'sharing_distribution','description':'iterate\x20sharing[],\x20split\x20by\x20mode\x20(Amount/Rate/RateGross/Surplus\x20placeholder)'},{'step':0x5,'action':'surplus_distribution','description':'withdraw_all\x20to\x20surplus_recipient\x20(if\x20any)'},{'step':0x6,'action':'recipient_resolution','description':'resolve\x20address\x20from\x20GuardIdentifier(passport)\x20/\x20Entity(static)\x20/\x20Signer(tx\x20sender);\x20GuardIdentifier\x20submissions\x20are\x20additionally\x20checked\x20against\x20payment_info.for_object\x20when\x20it\x20is\x20Some\x20(mismatch\x20aborts\x20ERECIPIENT_NOT_FOR_OBJECT\x2015;\x20None\x20=\x20no\x20anchor,\x20nothing\x20enforced)'},{'step':0x7,'action':'payment_creation','description':'create\x20Payment\x20object,\x20push\x20to\x20self.payment\x20vector'}];}export function buildDefaultRecipientRules(){return[{'recipient_type':'GuardIdentifier','resolution_source':'passport_table','safety_level':'safe'},{'recipient_type':'Entity','resolution_source':'static_address','safety_level':'safe'},{'recipient_type':'Signer','resolution_source':'tx_sender','safety_level':'dangerous'}];}export function buildDefaultLogicPuzzle(){return{'alloc_flow':buildDefaultAllocFlow(),'guard_matching_strategy':'caller_specified_guard','recipient_resolution_rules':buildDefaultRecipientRules()};}export const ALLOCATION_PUZZLE_VERSION='1.0.0';
|
|
@@ -40,7 +40,7 @@ export interface AllocationRiskCheckContext {
|
|
|
40
40
|
Signer: "signer";
|
|
41
41
|
};
|
|
42
42
|
sharing: string | number;
|
|
43
|
-
mode: "Amount" | "Rate" | "Surplus";
|
|
43
|
+
mode: "Amount" | "Rate" | "Surplus" | "RateGross";
|
|
44
44
|
}[];
|
|
45
45
|
fix?: string | number;
|
|
46
46
|
max?: string | number | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MAX_ALLOCATOR_COUNT,RATE_TOTAL_FULL,ALLOCATION_ERROR_CODES}from'./allocation-ledger.js';import{isUnboundSignerTheft}from'./recipient-constraint.js';import{getJudgmentDoc,factoryRulePack}from'../config/judgment.js';import{evaluateRuleBook,evaluateCondition}from'../config/rule-engine.js';const AUTO_FIXABLE=new Set(['R-A-1-02#0','R-A-1-02#1','R-A-1-03#0','R-A-1-03#2','R-A-2-03#0','R-A-5-03#0']),RELATED_MOVE_ERROR={'R-A-1-01#0':'EALLOCATORS_EMPTY\x20(8)\x20/\x20ENO_ALLOCATOR\x20(3)','R-A-1-01#1':'ENO_ALLOCATOR\x20(3)','R-A-1-02#0':'ERATE_NOT_10000\x20(4)','R-A-1-02#1':'ERATE_EXCEEDS_10000\x20(6)','R-A-1-03#0':'EMULTIPLE_SURPLUS\x20(5)','R-A-1-03#1':'EAMOUNT_BELOW_THRESHOLD\x20(12)','R-A-1-03#2':'EAMOUNT_EXCEEDS_MAX\x20(13)','R-A-2-02#0':'ERECIPIENT_IDENTIFIER_NOT_ADDRESS\x20(1)','R-A-2-04#0':'ERECIPIENT_NOT_FOR_OBJECT\x20(15)','R-A-2-04#1':'ERECIPIENT_NOT_FOR_OBJECT\x20(15,\x20only\x20fires\x20when\x20a\x20binding\x20is\x20declared)','R-A-5-01#0':'E_ALLOCATION_ALREADY_SPECIFIED','R-A-5-02#0':'ENO_PAYMENT_INFO\x20(9)'},RELATED_GUARD_RISK={'R-A-2-01#0':'R-C3-06','R-A-3-04#0':'R-C3-06\x20(Signer\x20binding)\x20/\x20time-lock\x20patterns','R-A-4-01#0':'R-X1-05','R-A-4-03#0':'reentrancy\x20low'};export function allocationRiskFacts(b){const c=b['allocators_config'],d=!!c,e=d?c['allocators']:[];let f,g;if(d&&e['length']>0x0)for(let P=0x0;P<e['length'];P++){if(e[P]['sharing']['length']===0x0){f=P,g=e[P]['guard'];break;}}let h,j,k,l=![],m=![];if(d)for(let Q=0x0;Q<e['length'];Q++){const R=e[Q],S=R['sharing']['filter'](U=>U['mode']==='Rate')['reduce']((U,V)=>U+Number(V['sharing']),0x0),T=R['sharing']['some'](U=>U['mode']==='Surplus');if(!T&&S>0x0&&S!==RATE_TOTAL_FULL){h=Q,j=R['guard'],k=S,l=!![];break;}if(T&&S>RATE_TOTAL_FULL){h=Q,j=R['guard'],k=S,m=!![];break;}}let n,o,p,q,r,t,u;if(d){const U=Number(c['threshold']);for(let V=0x0;V<e['length'];V++){const W=e[V],X=W['sharing']['filter'](Z=>Z['mode']==='Surplus')['length'];if(X>0x1){n='multiple_surplus',o=V,p=W['guard'],q=X;break;}const Y=W['sharing']['filter'](Z=>Z['mode']==='Amount')['reduce']((Z,a0)=>Z+Number(a0['sharing']),0x0);if(Y>0x0&&Y<U){n='below_threshold',o=V,p=W['guard'],r=Y,t=U;break;}if(W['max']!=null&&Y>Number(W['max'])){n='exceeds_max',o=V,p=W['guard'],r=Y,u=Number(W['max']);break;}}}let v=![],w,x,y;if(d)for(let Z=0x0;Z<e['length'];Z++){const a0=e[Z],a1=a0['sharing']['some'](a3=>'Signer'in a3['who']),a2=b['guard_signer_bindings']?.[a0['guard']]===!![];if(isUnboundSignerTheft({'recipient_is_signer':a1,'caller_identity_constrained':a2})){v=!![],w=Z,x=a0['guard'],y=a2;break;}}let z,A,B;if(d&&b['passport_identifier_types'])for(let a3=0x0;a3<e['length'];a3++){const a4=e[a3],a5=a4['sharing']['find'](a8=>'GuardIdentifier'in a8['who']);if(!a5)continue;const a6=a5['who']['GuardIdentifier'],a7=b['passport_identifier_types'][a6];if(a7!==undefined&&a7!=='address'){z=a6,A=a7,B=a3;break;}}let C=![],D,E,F,G;if(d){const a8=e['map'](aa=>aa['guard']),a9=new Set(a8);if(a9['size']!==a8['length']){const aa=a8['filter']((ab,ad)=>a8['indexOf'](ab)!==ad);C=!![],D=a8['length'],E=a9['size'],F=aa['join'](',\x20'),G=aa['join'](',');}}const H=b['payment_info_for_object']!==undefined,I=d&&e['some'](ab=>ab['sharing']['some'](ad=>'GuardIdentifier'in ad['who'])),J=!!b['payment_info_for_object'];let K=![],L,M;if(d&&b['referenced_treasuries_permissions']&&b['host_service_permission'])for(const ab of e){for(const ad of ab['sharing']){if(!(ad['who']!==null&&typeof ad['who']==='object'&&'Entity'in ad['who']))continue;const ae=ad['who']['Entity'],af=b['referenced_treasuries_permissions'][ae];if(af&&af!==b['host_service_permission']){K=!![],L=ae,M=af;break;}}if(K)break;}let N;if(b['trigger_source']==='standalone'&&d){const ag=[];for(const ah of e){const ai=b['guard_signer_bindings']?.[ah['guard']]===!![],aj=b['guard_has_time_lock']?.[ah['guard']]===!![];if(!ai&&!aj)ag['push'](ah['guard']);}N=ag;}let O;if(d)for(let ak=0x0;ak<e['length'];ak++){const al=e[ak],am=al['sharing']['length']>0x0&&al['sharing']['every'](an=>an['mode']==='Amount');if(am){O=ak;break;}}return{'allocators_config_present':d,'allocators_count':d?e['length']:undefined,'allocators_empty':d&&e['length']===0x0,'empty_sharing_allocator_index':f,'empty_sharing_allocator_guard':g,'rate_rule_index':h,'rate_rule_guard':j,'rate_rule_sum':k,'rate_rule_pure':l,'rate_rule_exceed':m,'rate_total_full':RATE_TOTAL_FULL,'amount_rule_branch':n,'amount_rule_index':o,'amount_rule_guard':p,'amount_rule_surplus_count':q,'amount_rule_amount_sum':r,'amount_rule_threshold':t,'amount_rule_max':u,'signer_theft_detected':v,'signer_theft_index':w,'signer_theft_guard':x,'signer_theft_guard_bound':y,'guard_id_bad_identifier':z,'guard_id_bad_type':A,'guard_id_bad_index':B,'duplicate_guards_present':C,'allocators_total':D,'allocators_unique':E,'duplicate_guards_csv_sp':F,'duplicate_guards_csv':G,'for_object_anchor_known':H,'guard_identifier_recipient_present':I,'for_object_anchor_set':J,'for_object_anchor':H&&J?b['payment_info_for_object']??undefined:undefined,'host_service_published':b['host_service_published'],'treasury_perm_mismatch':K,'treasury_perm_entity':L,'treasury_perm_treasury':M,'host_service_permission':b['host_service_permission'],'allocation_create_op':b['operation_type']==='create','allocation_standalone':b['trigger_source']==='standalone','trigger_source_display':b['trigger_source']??'unknown','standalone_weak_guards_count':N?.['length'],'standalone_weak_guards_csv_sp':N?.['join'](',\x20'),'standalone_weak_guards_csv':N?.['join'](','),'has_fallback_allocator':b['has_fallback_allocator'],'guard_conditions_mutually_exclusive':b['guard_conditions_mutually_exclusive'],'has_fallback_allocator_display':String(b['has_fallback_allocator']??![]),'mutually_exclusive_display':String(b['guard_conditions_mutually_exclusive']??![]),'pure_amount_index':O,'order_already_has_allocation':b['order_already_has_allocation'],'bound_order_display':b['bound_order']??'unknown','bound_order_paren_display':b['bound_order']??'(unknown)','has_payment_info':b['has_payment_info'],'operation_type':b['operation_type'],'max_allocator_count':MAX_ALLOCATOR_COUNT};}function allocationRuleBook(){const a=getJudgmentDoc()['rules']['domains']['allocation'];if(!a)throw new Error('factory\x20rule\x20pack\x20\x27allocation\x27\x20missing\x20—\x20broken\x20installation');return a['rules'];}function firedCaseKey(a,b,c){const d=a['find'](e=>e['rule_id']===c);if(d)for(let e=0x0;e<d['cases']['length'];e++){if(evaluateCondition(d['cases'][e]['when'],b))return c+'#'+e;}return c+'#0';}function findingToAllocationRisk(a,b){const c=RELATED_MOVE_ERROR[b],d=RELATED_GUARD_RISK[b];return{'id':a['rule_id'],'level':a['level'],'category':a['dimension']??'structural','title':a['title'],'description':a['description'],'affected_stakeholders':a['stakeholders']??[],'scenario':a['scenario']??'','mitigation':a['mitigation']??'','evidence':a['evidence'],...c!==undefined?{'related_move_error':c}:{},...d!==undefined?{'related_guard_risk':d}:{},'auto_fixable':AUTO_FIXABLE['has'](b),...a['exposure']!=null?{'exposure':a['exposure']}:{}};}export const ALLOCATION_RISK_VERSION='1.1.0';export function getAllRiskRules(){const a=factoryRulePack('allocation');if(!a)return[];return a['rules']['map'](b=>({'id':b['rule_id'],'category':b['dimension']??'structural','trigger':b['trigger']??'','check':c=>{const d=allocationRiskFacts(c),{findings:e}=evaluateRuleBook([b],d);return e['length']>0x0?findingToAllocationRisk(e[0x0],firedCaseKey([b],d,b['rule_id'])):null;}}));}export function assessAllocationRisks(a){const b=allocationRuleBook(),c=allocationRiskFacts(a),{findings:d}=evaluateRuleBook(b,c),e=d['map'](j=>findingToAllocationRisk(j,firedCaseKey(b,c,j['rule_id']))),f=e['length']===0x0?'low':e['some'](j=>j['level']==='critical')?'critical':e['some'](j=>j['level']==='high')?'high':e['some'](j=>j['level']==='medium')?'medium':'low',g={},h={};for(const j of e){g[j['category']]=(g[j['category']]??0x0)+0x1,h[j['level']]=(h[j['level']]??0x0)+0x1;}const i={};for(const k of e){for(const l of k['affected_stakeholders']){if(!i[l])i[l]=[];i[l]['push'](k['id']+':\x20'+k['mitigation']);}}return{'summary':'Assessed\x20'+e['length']+'\x20risk(s)\x20across\x20'+Object['keys'](g)['length']+'\x20categories','risks':e,'overall_risk':f,'risks_by_category':g,'risks_by_level':h,'stakeholder_advice':i,'needs_human_review':e['some'](m=>m['level']==='critical'||m['level']==='high'),'blocks_publish':e['some'](m=>m['level']==='critical')};}export{ALLOCATION_ERROR_CODES};
|
|
1
|
+
import{MAX_ALLOCATOR_COUNT,RATE_TOTAL_FULL,ALLOCATION_ERROR_CODES}from'./allocation-ledger.js';import{isUnboundSignerTheft}from'./recipient-constraint.js';import{getJudgmentDoc,factoryRulePack}from'../config/judgment.js';import{evaluateRuleBook,evaluateCondition}from'../config/rule-engine.js';const AUTO_FIXABLE=new Set(['R-A-1-02#0','R-A-1-02#1','R-A-1-02#2','R-A-1-02#3','R-A-1-02#4','R-A-1-03#0','R-A-1-03#2','R-A-2-03#0','R-A-5-03#0']),RELATED_MOVE_ERROR={'R-A-1-01#0':'EALLOCATORS_EMPTY\x20(8)\x20/\x20ENO_ALLOCATOR\x20(3)','R-A-1-01#1':'ENO_ALLOCATOR\x20(3)','R-A-1-02#0':'ERATE_NOT_10000\x20(4)','R-A-1-02#1':'ERATE_EXCEEDS_10000\x20(6)','R-A-1-02#2':'ERATE_EXCEEDS_10000\x20(6)','R-A-1-02#3':'ERATE_EXCEEDS_10000\x20(6)','R-A-1-02#4':'ERATE_EXCEEDS_10000\x20(6)','R-A-1-02#5':'EMIXED_RATE_BASES\x20(17)','R-A-1-03#0':'EMULTIPLE_SURPLUS\x20(5)','R-A-1-03#1':'EAMOUNT_BELOW_THRESHOLD\x20(12)','R-A-1-03#2':'EAMOUNT_EXCEEDS_MAX\x20(13)','R-A-2-02#0':'ERECIPIENT_IDENTIFIER_NOT_ADDRESS\x20(1)','R-A-2-04#0':'ERECIPIENT_NOT_FOR_OBJECT\x20(15)','R-A-2-04#1':'ERECIPIENT_NOT_FOR_OBJECT\x20(15,\x20only\x20fires\x20when\x20a\x20binding\x20is\x20declared)','R-A-5-01#0':'E_ALLOCATION_ALREADY_SPECIFIED','R-A-5-02#0':'ENO_PAYMENT_INFO\x20(9)'},RELATED_GUARD_RISK={'R-A-2-01#0':'R-C3-06','R-A-3-04#0':'R-C3-06\x20(Signer\x20binding)\x20/\x20time-lock\x20patterns','R-A-4-01#0':'R-X1-05','R-A-4-03#0':'reentrancy\x20low'};export function allocationRiskFacts(b){const c=b['allocators_config'],d=!!c,e=d?c['allocators']:[];let f,g;if(d&&e['length']>0x0)for(let Z=0x0;Z<e['length'];Z++){if(e[Z]['sharing']['length']===0x0){f=Z,g=e[Z]['guard'];break;}}let h,j,k,l=![],n=![];if(d)for(let a0=0x0;a0<e['length'];a0++){const a1=e[a0],a2=a1['sharing']['some'](a9=>a9['mode']==='RateGross'),a3=a1['sharing']['filter'](a9=>a9['mode']==='Amount')['reduce']((a9,aa)=>a9+Number(aa['sharing']),0x0);if(a2&&a3>0x0)continue;const a4=a2&&a3===0x0&&a1['sharing']['some'](a9=>a9['mode']==='Rate'),a5=a1['sharing']['filter'](a9=>a9['mode']==='Rate'||a4&&a9['mode']==='RateGross');if(a5['length']===0x0)continue;const a6=a5['map'](a9=>Number(a9['sharing']));if(a6['some'](a9=>!Number['isFinite'](a9)))continue;const a7=a6['reduce']((a9,aa)=>a9+aa,0x0),a8=a1['sharing']['some'](a9=>a9['mode']==='Surplus');if(!a8&&a7!==RATE_TOTAL_FULL){h=a0,j=a1['guard'],k=a7,l=!![];break;}if(a8&&a7>RATE_TOTAL_FULL){h=a0,j=a1['guard'],k=a7,n=!![];break;}}let o,p,q,r,t,u,v=![],w,x;if(d)for(let a9=0x0;a9<e['length'];a9++){const aa=e[a9],ab=aa['sharing']['some'](ah=>ah['mode']==='Rate'),ad=aa['sharing']['filter'](ah=>ah['mode']==='RateGross');if(ad['length']===0x0)continue;const ae=aa['sharing']['filter'](ah=>ah['mode']==='Amount')['reduce']((ah,ai)=>ah+Number(ai['sharing']),0x0);if(ab){if(ae>0x0){v=!![],w=a9,x=aa['guard'];break;}continue;}const af=ad['map'](ah=>Number(ah['sharing']));if(af['some'](ah=>!Number['isFinite'](ah))||!Number['isFinite'](ae))continue;const ag=af['reduce']((ah,ai)=>ah+ai,0x0);if(ag>RATE_TOTAL_FULL){o='sum_exceeds_10000',p=a9,q=aa['guard'],r=ag,t=ae;break;}if(aa['max']!=null){const ah=Number(aa['max']);if(Number['isFinite'](ah)&&ae*RATE_TOTAL_FULL+ag*ah>ah*RATE_TOTAL_FULL){o='cap_fit',p=a9,q=aa['guard'],r=ag,t=ae,u=ah;break;}}else{if(ae>0x0&&ag>=RATE_TOTAL_FULL){o='fixed_full',p=a9,q=aa['guard'],r=ag,t=ae;break;}}}let y,z,A,B,C,D,E;if(d){const ai=Number(c['threshold']);for(let aj=0x0;aj<e['length'];aj++){const ak=e[aj],al=ak['sharing']['filter'](ao=>ao['mode']==='Surplus')['length'];if(al>0x1){y='multiple_surplus',z=aj,A=ak['guard'],B=al;break;}const am=ak['sharing']['filter'](ao=>ao['mode']==='Amount')['reduce']((ao,ap)=>ao+Number(ap['sharing']),0x0),an=ak['sharing']['some'](ao=>ao['mode']==='Rate'||ao['mode']==='Surplus');if(!an&&am>0x0&&am<ai){y='below_threshold',z=aj,A=ak['guard'],C=am,D=ai;break;}if(ak['max']!=null&&am>Number(ak['max'])){y='exceeds_max',z=aj,A=ak['guard'],C=am,E=Number(ak['max']);break;}}}let F=![],G,H,I;if(d)for(let ao=0x0;ao<e['length'];ao++){const ap=e[ao],aq=ap['sharing']['some'](as=>'Signer'in as['who']),ar=b['guard_signer_bindings']?.[ap['guard']]===!![];if(isUnboundSignerTheft({'recipient_is_signer':aq,'caller_identity_constrained':ar})){F=!![],G=ao,H=ap['guard'],I=ar;break;}}let J,K,L;if(d&&b['passport_identifier_types'])for(let as=0x0;as<e['length'];as++){const at=e[as],au=at['sharing']['find'](ax=>'GuardIdentifier'in ax['who']);if(!au)continue;const av=au['who']['GuardIdentifier'],aw=b['passport_identifier_types'][av];if(aw!==undefined&&aw!=='address'){J=av,K=aw,L=as;break;}}let M=![],N,O,P,Q;if(d){const ax=e['map'](az=>az['guard']),ay=new Set(ax);if(ay['size']!==ax['length']){const az=ax['filter']((aA,aB)=>ax['indexOf'](aA)!==aB);M=!![],N=ax['length'],O=ay['size'],P=az['join'](',\x20'),Q=az['join'](',');}}const R=b['payment_info_for_object']!==undefined,S=d&&e['some'](aA=>aA['sharing']['some'](aB=>'GuardIdentifier'in aB['who'])),T=!!b['payment_info_for_object'];let U=![],V,W;if(d&&b['referenced_treasuries_permissions']&&b['host_service_permission'])for(const aA of e){for(const aB of aA['sharing']){if(!(aB['who']!==null&&typeof aB['who']==='object'&&'Entity'in aB['who']))continue;const aC=aB['who']['Entity'],aD=b['referenced_treasuries_permissions'][aC];if(aD&&aD!==b['host_service_permission']){U=!![],V=aC,W=aD;break;}}if(U)break;}let X;if(b['trigger_source']==='standalone'&&d){const aE=[];for(const aF of e){const aG=b['guard_signer_bindings']?.[aF['guard']]===!![],aH=b['guard_has_time_lock']?.[aF['guard']]===!![];if(!aG&&!aH)aE['push'](aF['guard']);}X=aE;}let Y;if(d)for(let aI=0x0;aI<e['length'];aI++){const aJ=e[aI],aK=aJ['sharing']['length']>0x0&&aJ['sharing']['every'](aL=>aL['mode']==='Amount');if(aK){Y=aI;break;}}return{'allocators_config_present':d,'allocators_count':d?e['length']:undefined,'allocators_empty':d&&e['length']===0x0,'empty_sharing_allocator_index':f,'empty_sharing_allocator_guard':g,'rate_rule_index':h,'rate_rule_guard':j,'rate_rule_sum':k,'rate_rule_pure':l,'rate_rule_exceed':n,'rate_total_full':RATE_TOTAL_FULL,'rate_gross_branch':o,'rate_gross_index':p,'rate_gross_guard':q,'rate_gross_sum':r,'rate_gross_fix':t,'rate_gross_max':u,'mixed_rate_bases_present':v,'mixed_rate_bases_index':w,'mixed_rate_bases_guard':x,'amount_rule_branch':y,'amount_rule_index':z,'amount_rule_guard':A,'amount_rule_surplus_count':B,'amount_rule_amount_sum':C,'amount_rule_threshold':D,'amount_rule_max':E,'signer_theft_detected':F,'signer_theft_index':G,'signer_theft_guard':H,'signer_theft_guard_bound':I,'guard_id_bad_identifier':J,'guard_id_bad_type':K,'guard_id_bad_index':L,'duplicate_guards_present':M,'allocators_total':N,'allocators_unique':O,'duplicate_guards_csv_sp':P,'duplicate_guards_csv':Q,'for_object_anchor_known':R,'guard_identifier_recipient_present':S,'for_object_anchor_set':T,'for_object_anchor':R&&T?b['payment_info_for_object']??undefined:undefined,'host_service_published':b['host_service_published'],'treasury_perm_mismatch':U,'treasury_perm_entity':V,'treasury_perm_treasury':W,'host_service_permission':b['host_service_permission'],'allocation_create_op':b['operation_type']==='create','allocation_standalone':b['trigger_source']==='standalone','trigger_source_display':b['trigger_source']??'unknown','standalone_weak_guards_count':X?.['length'],'standalone_weak_guards_csv_sp':X?.['join'](',\x20'),'standalone_weak_guards_csv':X?.['join'](','),'has_fallback_allocator':b['has_fallback_allocator'],'guard_conditions_mutually_exclusive':b['guard_conditions_mutually_exclusive'],'has_fallback_allocator_display':String(b['has_fallback_allocator']??![]),'mutually_exclusive_display':String(b['guard_conditions_mutually_exclusive']??![]),'pure_amount_index':Y,'order_already_has_allocation':b['order_already_has_allocation'],'bound_order_display':b['bound_order']??'unknown','bound_order_paren_display':b['bound_order']??'(unknown)','has_payment_info':b['has_payment_info'],'operation_type':b['operation_type'],'max_allocator_count':MAX_ALLOCATOR_COUNT};}function allocationRuleBook(){const a=getJudgmentDoc()['rules']['domains']['allocation'];if(!a)throw new Error('factory\x20rule\x20pack\x20\x27allocation\x27\x20missing\x20—\x20broken\x20installation');return a['rules'];}function firedCaseKey(a,b,c){const d=a['find'](e=>e['rule_id']===c);if(d)for(let e=0x0;e<d['cases']['length'];e++){if(evaluateCondition(d['cases'][e]['when'],b))return c+'#'+e;}return c+'#0';}function findingToAllocationRisk(a,b){const c=RELATED_MOVE_ERROR[b],d=RELATED_GUARD_RISK[b];return{'id':a['rule_id'],'level':a['level'],'category':a['dimension']??'structural','title':a['title'],'description':a['description'],'affected_stakeholders':a['stakeholders']??[],'scenario':a['scenario']??'','mitigation':a['mitigation']??'','evidence':a['evidence'],...c!==undefined?{'related_move_error':c}:{},...d!==undefined?{'related_guard_risk':d}:{},'auto_fixable':AUTO_FIXABLE['has'](b),...a['exposure']!=null?{'exposure':a['exposure']}:{}};}export const ALLOCATION_RISK_VERSION='1.1.0';export function getAllRiskRules(){const a=factoryRulePack('allocation');if(!a)return[];return a['rules']['map'](b=>({'id':b['rule_id'],'category':b['dimension']??'structural','trigger':b['trigger']??'','check':c=>{const d=allocationRiskFacts(c),{findings:e}=evaluateRuleBook([b],d);return e['length']>0x0?findingToAllocationRisk(e[0x0],firedCaseKey([b],d,b['rule_id'])):null;}}));}export function assessAllocationRisks(a){const b=allocationRuleBook(),c=allocationRiskFacts(a),{findings:d}=evaluateRuleBook(b,c),e=d['map'](j=>findingToAllocationRisk(j,firedCaseKey(b,c,j['rule_id']))),f=e['length']===0x0?'low':e['some'](j=>j['level']==='critical')?'critical':e['some'](j=>j['level']==='high')?'high':e['some'](j=>j['level']==='medium')?'medium':'low',g={},h={};for(const j of e){g[j['category']]=(g[j['category']]??0x0)+0x1,h[j['level']]=(h[j['level']]??0x0)+0x1;}const i={};for(const k of e){for(const l of k['affected_stakeholders']){if(!i[l])i[l]=[];i[l]['push'](k['id']+':\x20'+k['mitigation']);}}return{'summary':'Assessed\x20'+e['length']+'\x20risk(s)\x20across\x20'+Object['keys'](g)['length']+'\x20categories','risks':e,'overall_risk':f,'risks_by_category':g,'risks_by_level':h,'stakeholder_advice':i,'needs_human_review':e['some'](m=>m['level']==='critical'||m['level']==='high'),'blocks_publish':e['some'](m=>m['level']==='critical')};}export{ALLOCATION_ERROR_CODES};
|