Fix InsuranceContractError build break; add pause/unpause, transferInvoice, convertInvoiceToken; harden disputeInvoice - #512
Merged
Levi-Ojukwu merged 5 commits intoJul 25, 2026
Conversation
PR Invoice-Liquidity-Network#508 (issues 475-478) added a local InsuranceContractError class directly in insurance.ts. PR Invoice-Liquidity-Network#510 (issues 459-465, merged after) added a second, separately-written InsuranceContractError to errors.ts and imported it into insurance.ts. Both PRs' diffs were additive (new import lines, new class blocks) so they merged into main without a git conflict marker, but the result doesn't compile: duplicate identifier errors in index.ts and insurance.ts, plus literal duplicate import statements in insurance.test.ts (InsuranceContractError, and separately SorobanRpc/ Keypair/Address) merged in from both PRs' test-file edits. Keeps insurance.ts's original local class (the one actually used at runtime by its own simulateCall/submitCall) and removes the duplicate from errors.ts, the now-dangling import in insurance.ts, and the duplicate import lines in insurance.test.ts. `npx tsc --noEmit` in sdk/ now shows zero errors beyond the one pre-existing unrelated xdrDecoder.ts issue; full vitest suite matches the known baseline (11 pre-existing unrelated failures in getTokenDecimals.test.ts/nft.test.ts).
(closes Invoice-Liquidity-Network#470) pause(client)/unpause(client) wrap the contract's pause()/unpause() emergency admin controls. Both require the contract admin's signature — client.signer must be the stored admin — and map simulation errors (e.g. Unauthorized) through the existing ILNError.fromError. Adds tests for both, including the no-signer guard and error mapping.
(closes Invoice-Liquidity-Network#469) transferInvoice(client, invoiceId, newFreelancer) wraps transfer_invoice(invoice_id, new_freelancer), requiring the invoice's *current* freelancer's signature. Validates the invoice is currently Pending client-side (via getInvoice) before submitting — the contract enforces this too and updates the submitter index on both the old and new freelancer. Adds tests covering the happy path, the Pending-status validation, and the no-signer guard.
(closes Invoice-Liquidity-Network#468) convertInvoiceToken(client, freelancerAddress, invoiceId, newToken) wraps convert_invoice_token(freelancer, invoice_id, new_token), requiring the freelancer's signature. Validates the invoice is currently Pending client-side before submitting. Note: token-approval is enforced entirely by the contract — there's no public query to check the allowlist client-side, so an unapproved token surfaces as ILNError.Unauthorized from the simulation rather than a pre-flight check, documented in the JSDoc. Adds tests covering the happy path, Pending-status validation, and error-code mapping for an unapproved token.
(closes Invoice-Liquidity-Network#464) disputeInvoice previously relied on rpc.prepareTransaction's implicit simulation, which throws raw (untyped) errors — no ILNError mapping at all. Rewrote the write path to explicitly simulate, check isSimulationError, and throw through ILNError.fromError, so callers get typed errors (AlreadyDisputed, InvoiceDefaulted, InvoiceExpired, etc.) instead of opaque RPC exceptions. Added a pre-flight check: fetches the invoice via getInvoice and validates it's in a disputable status (Pending/PartiallyFunded/Funded, mirroring the contract's own match arm) before submitting. Retry-with-backoff was already present via the existing retry() utility on getAccount/prepareTransaction/sendTransaction — extended it to the new simulateTransaction/getNetwork calls too, and expanded the JSDoc with the full set of @throws now that they're typed. Adds a test file for this method (previously had none) covering the happy path, the pre-flight status check, and error-code mapping.
|
@Temi-suwa18 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
InsuranceContractErrorclass — one directly ininsurance.ts, one inerrors.ts(re-imported intoinsurance.ts). Both diffs were purely additive so they merged without a conflict marker, but the result doesn't compile: duplicate identifiers inindex.ts/insurance.ts, and literal duplicate import statements ininsurance.test.tsmerged in from both PRs. Fixed by keepinginsurance.ts's original class (the one actually used at runtime) and removing the duplicate.#470 — pause/unpause.
pause(client)/unpause(client)wrap the contract's emergency admin controls, requiring the admin's signature.#469 — transferInvoice.
transferInvoice(client, invoiceId, newFreelancer)wrapstransfer_invoice, requiring the current freelancer's signature, and validates the invoice isPendingclient-side before submitting.#468 — convertInvoiceToken.
convertInvoiceToken(client, freelancerAddress, invoiceId, newToken)wrapsconvert_invoice_token, validatingPendingstatus client-side. Token-approval itself is contract-enforced only (no public allowlist query exists to check client-side), so an unapproved token surfaces asILNError.Unauthorizedfrom simulation rather than a fabricated pre-flight check — documented in the JSDoc.#464 — disputeInvoice hardening. Previously relied on
rpc.prepareTransaction's implicit simulation, which threw raw untyped errors — noILNErrormapping at all, and no test file existed for it. Rewrote the write path to explicitly simulate and map throughILNError.fromError, added a pre-flight status check (Pending/PartiallyFunded/Funded, mirroring the contract's own match arm), and added a full test file. Retry-with-backoff was already present via the existingretry()utility on the account/tx calls — extended it to the newly-addedsimulateTransaction/getNetworkcalls too.Closes #464
Closes #468
Closes #469
Closes #470
Test plan
npx vitest runinsdk/: all new tests pass acrossadminControls.test.ts/transferInvoice.test.ts/convertInvoiceToken.test.ts/disputeInvoice.test.ts(new file), plus the now-fixedinsurance.test.ts; 11 pre-existing unrelated failures (getTokenDecimals.test.ts,nft.test.ts) confirmed to already exist onmainnpx tsc --noEmitinsdk/: zero new errors (including theInsuranceContractErrorduplicate-identifier errors, now fixed); one pre-existing unrelated error inxdrDecoder.ts