Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions data/smart_contracts.json
Original file line number Diff line number Diff line change
Expand Up @@ -921,16 +921,6 @@
"name": "Vote Gov Params",
"sourceIdentifier": "VoteGovParams"
},
{
"id": 5,
"name": "Create Asset Release Poll",
"sourceIdentifier": "CreateAssetReleasePoll"
},
{
"id": 6,
"name": "Vote Asset Release",
"sourceIdentifier": "VoteAssetRelease"
},
{
"id": 7,
"name": "Deposit General Asset",
Expand Down
38 changes: 33 additions & 5 deletions scripts/update_smart_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
- address: computed via Node using your JS helper:
const publicKey = helper.getIdentityBytes(addr56); // addr56 built from contractIndex (A..P, LE, len=56)
const identity = await helper.getIdentity(publicKey) // 60-char with checksum
- Non-destructive merge: adds new contracts and new procedure IDs; preserves manual edits and custom fields.
- Merge: adds new contracts and new procedure IDs, and removes script-generated procedures
(those with a `sourceIdentifier`) that no longer exist in a successfully-fetched source.
Manual edits (procedures without `sourceIdentifier`) and custom fields are always preserved.
Procedure removal is suppressed for a contract whose source failed to fetch or fetched empty,
so a transient/garbage response can't wipe its procedures.
Authoritative fields (auto-updated from GitHub): filename, name, contractIndex, address, githubUrl,
firstUseEpoch, sharesAuctionEpoch, allowTransferShares, procedures.
Preserved fields: label (if already set), and any custom fields (e.g., proposalUrl, etc.).
Expand Down Expand Up @@ -603,8 +607,14 @@ def merge_contracts(
if not isinstance(fname, str):
continue

# Transient flag (not persisted): whether the contract source was fetched
# successfully this run. Used to safely prune procedures removed upstream.
source_fetched = bool(new.pop("_sourceFetched", False))

if fname not in by_filename:
new["procedures"] = normalize_procs_to_list(new.get("procedures", []))
print(f" {fname}: new contract added (index {new.get('contractIndex')}, "
f"{len(new['procedures'])} procedure(s))")
existing.append(new)
by_filename[fname] = new
continue
Expand Down Expand Up @@ -679,14 +689,30 @@ def merge_contracts(
merged_procs.append(ex_p)
else:
# New procedure
print(f" {fname}: procedure id {pid} ({new_p.get('sourceIdentifier')}) "
f"added from source")
merged_procs.append(new_p)
seen_ids.add(pid)

# Keep any existing procedures that are no longer in the fresh list
# (in case they were manually added)
# Handle existing procedures that are no longer in the fresh list.
# Only prune when the fetch yielded at least one procedure. A 200 response
# with a truncated/garbage body parses to zero procedures, which would
# otherwise wipe a contract's entire procedure list (N -> 0); requiring a
# non-empty fresh list still prunes individually removed procedures.
fresh_has_procs = len(new_list) > 0
for pid, p in ex_by_id.items():
if pid not in seen_ids:
merged_procs.append(p)
if pid in seen_ids:
continue
# A script-generated procedure (has sourceIdentifier) that vanished from a
# successfully-fetched source was removed upstream -> drop it. Procedures
# without a sourceIdentifier are manual additions and are always preserved.
# Guard on source_fetched + fresh_has_procs so a transient fetch failure
# or a bad-but-200 response can't wipe procedures.
if source_fetched and fresh_has_procs and isinstance(p, dict) and p.get("sourceIdentifier"):
print(f" {fname}: procedure id {pid} ({p.get('sourceIdentifier')}) "
f"removed from source, dropping")
continue
merged_procs.append(p)

merged_procs.sort(key=lambda x: x["id"])
ex["procedures"] = merged_procs
Expand Down Expand Up @@ -797,6 +823,8 @@ def main():
"address": addr,
"allowTransferShares": allow_transfer_shares,
"procedures": procs,
# Transient (popped during merge): did we fetch the source this run?
"_sourceFetched": text is not None,
}

if construction_epoch is not None:
Expand Down
Loading