forked from onflow/fcl-js
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathresolve-accounts.js
97 lines (88 loc) · 2.95 KB
/
resolve-accounts.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import {invariant} from "@onflow/util-invariant"
import {isTransaction} from "../interaction/interaction.js"
import {createSignableVoucher} from "./voucher.js"
const isFn = v => typeof v === "function"
export function buildPreSignable(acct, ix) {
try {
return {
f_type: "PreSignable",
f_vsn: "1.0.1",
roles: acct.role,
cadence: ix.message.cadence,
args: ix.message.arguments.map(d => ix.arguments[d].asArgument),
data: {},
interaction: ix,
voucher: createSignableVoucher(ix),
}
} catch (error) {
console.error("buildPreSignable", error)
throw error
}
}
async function collectAccounts(ix, accounts, last, depth = 3) {
invariant(depth, "Account Resolve Recursion Limit Exceeded", {ix, accounts})
let authorizations = []
for (let ax of accounts) {
var old = last || ax
if (isFn(ax.resolve)) ax = await ax.resolve(ax, buildPreSignable(ax, ix))
if (Array.isArray(ax)) {
await collectAccounts(ix, ax, old, depth - 1)
} else {
if (ax.addr != null && ax.keyId != null) {
ax.tempId = `${ax.addr}-${ax.keyId}`
}
ix.accounts[ax.tempId] = ix.accounts[ax.tempId] || ax
ix.accounts[ax.tempId].role.proposer =
ix.accounts[ax.tempId].role.proposer || ax.role.proposer
ix.accounts[ax.tempId].role.payer =
ix.accounts[ax.tempId].role.payer || ax.role.payer
ix.accounts[ax.tempId].role.authorizer =
ix.accounts[ax.tempId].role.authorizer || ax.role.authorizer
if (ix.accounts[ax.tempId].role.proposer && ix.proposer === old.tempId) {
ix.proposer = ax.tempId
}
if (ix.accounts[ax.tempId].role.payer && ix.payer === old.tempId) {
ix.payer = ax.tempId
}
if (ix.accounts[ax.tempId].role.authorizer) {
if (last) {
// do group replacement
authorizations = Array.from(new Set([...authorizations, ax.tempId]))
} else {
// do 1-1 replacement
ix.authorizations = ix.authorizations.map(d =>
d === old.tempId ? ax.tempId : d
)
// if (!new Set(ix.authorizations).has(ax.tempId)) {
// ix.authorizations = Array.from(
// new Set([...ix.authorizations, ax.tempId])
// )
// }
}
}
}
if (old.tempId != ax.tempId) delete ix.accounts[old.tempId]
}
if (last) {
// complete (flatmap) group replacement
ix.authorizations = ix.authorizations
.map(d => (d === last.tempId ? authorizations : d))
.reduce(
(prev, curr) =>
Array.isArray(curr) ? [...prev, ...curr] : [...prev, curr],
[]
)
}
}
export async function resolveAccounts(ix) {
if (isTransaction(ix)) {
try {
await collectAccounts(ix, Object.values(ix.accounts))
await collectAccounts(ix, Object.values(ix.accounts))
} catch (error) {
console.error("=== SAD PANDA ===\n\n", error, "\n\n=== SAD PANDA ===")
throw error
}
}
return ix
}