Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { beginCell, Cell, contractAddress } from '@ton/ton';
import { Buffer } from 'buffer';

// Per-account "trampoline" of the Telegram wallet (WalletTg): the only code deployed
// for each account. The actual WalletTg bytecode lives in the network config
// (param -123), and the trampoline jumps into it, so the state init code below
// never changes across WalletTg revisions.
const walletTgTrampolineCode = 'te6cckEBAQEAGgAAMP8AIJgh10mDCLnyQN+Ahfgz0O0eIO1T2WlCfjk=';

// 0xXX prefix of the current WalletTg storage layout (bumped on each contract revision).
const walletTgStorageRevision = 0x00;

export const WALLET_TG_SUBWALLET_ID_MAINNET = 0x7fff7f11;
export const WALLET_TG_SUBWALLET_ID_TESTNET = 0x7fff7ffd;

export class WalletContractTg {
static create(args: { workchain: number; publicKey: Buffer; walletId?: number | null }) {
const code = Cell.fromBase64(walletTgTrampolineCode);
const data = beginCell()
.storeUint(walletTgStorageRevision, 8)
.storeUint(0, 32) // seqno
.storeUint(args.walletId ?? WALLET_TG_SUBWALLET_ID_MAINNET, 32)
.storeBuffer(args.publicKey, 32)
.endCell();
const init = { code, data };
return { init, address: contractAddress(args.workchain, init) };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@ton/ton';
import { Buffer } from 'buffer';
import { WalletContractV4R1 } from './wallet-contract-v4-r1';
import { WalletContractTg } from './wallet-contract-tg';

const knownWallets = [
{ contract: WalletContractV1R1, loadData: loadWalletV1Data },
Expand All @@ -26,7 +27,8 @@ const knownWallets = [
{ contract: WalletContractV4R1, loadData: loadWalletV4Data },
{ contract: WalletContractV4R2, loadData: loadWalletV4Data },
{ contract: WalletContractV5Beta, loadData: loadWalletV5BetaData },
{ contract: WalletContractV5R1, loadData: loadWalletV5Data }
{ contract: WalletContractV5R1, loadData: loadWalletV5Data },
{ contract: WalletContractTg, loadData: loadWalletTgData }
].map(({ contract, loadData }) => ({
contract: contract,
loadData: loadData,
Expand Down Expand Up @@ -78,6 +80,16 @@ function loadWalletV5Data(cs: Slice) {
return { isSignatureAuthAllowed, seqno, publicKey, walletId, plugins };
}

function loadWalletTgData(cs: Slice) {
// A future WalletTg revision may append fields after publicKey, so the
// remainder of the cell is intentionally left unread.
const storageRevision = cs.loadUint(8);
const seqno = cs.loadUint(32);
const walletId = cs.loadUint(32);
const publicKey = cs.loadBuffer(32);
return { storageRevision, seqno, walletId, publicKey };
}

export function tryParsePublicKey(stateInit: StateInit): Buffer | null {
if (!stateInit.code || !stateInit.data) {
return null;
Expand Down