@droplinked_inc/web3
v3.0.0
Published
Per-shop EVM contract interactions for droplinked (shop deploy, product record, purchase signing, claim, airdrop). Hardened rebuild — replaces the hostile-published [email protected] by k3rn3lpanic.
Readme
@droplinked_inc/web3
Per-shop EVM contract interactions for droplinked: shop deployment, product recording, EIP-712 purchase signing + verification, claim, airdrop, ERC-20 token transfers.
This package replaces the hostile-published [email protected]
(npm author k3rn3lpanic — the same identity that owns
droplinked-payment-intent). Zero code is reused from the
original; every export was re-implemented from the published .d.ts
type surface and canonical Solidity signatures.
MOST security-critical package in the
@droplinked_inc/*rebuild. Read THREAT_MODEL.md before any review.
Install
pnpm add @droplinked_inc/web3 @droplinked_inc/wallet-connection @droplinked_inc/web3-kit@droplinked_inc/wallet-connection and @droplinked_inc/web3-kit are
peer dependencies — they own the wallet protocol and the chain
registry respectively. This package owns the contract-call surface.
Usage
Build a purchase call
import {
DropWeb3,
Network,
Chain,
ChainWallet,
renderCallForConfirmation,
} from '@droplinked_inc/web3';
const web3 = new DropWeb3(Network.MAINNET);
const inst = web3.web3Instance({
chain: Chain.POLYGON,
preferredWallet: ChainWallet.Metamask,
shopContractAddress: '0x...', // pinned at construction; never fetched
});
const call = inst.buildPurchaseCall(paymentDataFromBackend);
// SECURITY: always surface the canonical form before passing to a wallet.
const confirmation = renderCallForConfirmation(call);
console.log(confirmation.functionName, confirmation.argsJson);
// Then submit via @droplinked_inc/wallet-connection.Verify a purchase signature (server-side)
import {
ShopContract,
verifyPurchaseSignature,
} from '@droplinked_inc/web3';
const shop = new ShopContract({ address: shopAddr, publicClient });
const onChainNonce = await shop.readPurchaseNonce(buyer);
await verifyPurchaseSignature({
signature: signaturePayload,
expectedSigner: buyer,
onChainNonce,
});Privileged actions
const call = inst.buildSetSignerCall(newSigner, {
acknowledgePrivilegedAction: true, // required literal
});Security model in one line
Every contract call goes through a typed client built from a
known-good as const ABI. Selectors are computed structurally and
cross-checked at module load. ERC-20 approve / permit /
setApprovalForAll and NFT safeTransferFrom are explicitly on the
KNOWN_DRAINER_SELECTORS list and are NEVER produced by this package.
Per-method security warnings
| Method | Warning |
|---|---|
| encodeErc20Transfer | Receiver address is taken at face value. Surface the address back to the user via renderCallForConfirmation before signing. |
| buildSetSigner / buildSetManager | Privileged. Requires { acknowledgePrivilegedAction: true }. A compromised admin EOA that calls this rotates the signer to an attacker — operationally mitigated by hardware-wallet ownership of the admin key. |
| encodeDroplinkedPurchase | The tokenAddress is taken at face value. Pin it via @droplinked_inc/web3-kit's registry, do not fetch from a runtime API. |
| verifyPurchaseSignature | MUST be called server-side with a fresh on-chain nonce read. Caching the nonce defeats replay protection. |
| buildPurchaseTypedData | Items are explicitly copied (no spread of caller input). The signed payload includes chainId, verifyingContract, shopAddress, nonce, and deadline. |
Reviewers
- See THREAT_MODEL.md for the per-attack mitigation matrix (T1–T17).
- See MIGRATION.md for the consumer mapping from
[email protected]. - A formal third-party security audit is recommended BEFORE the first consumer migration. Scope is documented at the bottom of THREAT_MODEL.md.
Status
v0.0.0 — initial rebuild. Not yet published to npm.
