Skip to content

Commit 6fee38f

Browse files
committed
chore: add wrappers examples for react doc
1 parent da2fba1 commit 6fee38f

File tree

1 file changed

+251
-0
lines changed

1 file changed

+251
-0
lines changed

docs/develop/dapps/ton-connect/react.mdx

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,257 @@ const [tonConnectUI] = useTonConnectUI();
330330
await tonConnectUI.disconnect();
331331
```
332332
333+
## Wrappers
334+
335+
Wrappers are classes that simplify interaction with the contract, allowing you to work without concerning yourself with the underlying details.
336+
337+
- When developing a contract in `funC`, you need to write the wrapper yourself.
338+
- When using the `Tact` language, wrappers are automatically generated for you.
339+
340+
:::tip
341+
Check out [blueprint](https://github.com/ton-org/blueprint) documentation how to develop and deploy contracts
342+
:::
343+
344+
Let's take a look at the default `Blueprint` Counter wrapper example and how we can use it:
345+
346+
<details>
347+
<summary>Wrapper usage</summary>
348+
Counter wrapper class:
349+
350+
```ts
351+
import { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode } from '@ton/core';
352+
353+
export type CounterConfig = {
354+
id: number;
355+
counter: number;
356+
};
357+
358+
export function counterConfigToCell(config: CounterConfig): Cell {
359+
return beginCell().storeUint(config.id, 32).storeUint(config.counter, 32).endCell();
360+
}
361+
362+
export const Opcodes = {
363+
increase: 0x7e8764ef,
364+
};
365+
366+
export class Counter implements Contract {
367+
constructor(
368+
readonly address: Address,
369+
readonly init?: { code: Cell; data: Cell },
370+
) {}
371+
372+
static createFromAddress(address: Address) {
373+
return new Counter(address);
374+
}
375+
376+
static createFromConfig(config: CounterConfig, code: Cell, workchain = 0) {
377+
const data = counterConfigToCell(config);
378+
const init = { code, data };
379+
return new Counter(contractAddress(workchain, init), init);
380+
}
381+
382+
async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
383+
await provider.internal(via, {
384+
value,
385+
sendMode: SendMode.PAY_GAS_SEPARATELY,
386+
body: beginCell().endCell(),
387+
});
388+
}
389+
390+
async sendIncrease(
391+
provider: ContractProvider,
392+
via: Sender,
393+
opts: {
394+
increaseBy: number;
395+
value: bigint;
396+
queryID?: number;
397+
},
398+
) {
399+
await provider.internal(via, {
400+
value: opts.value,
401+
sendMode: SendMode.PAY_GAS_SEPARATELY,
402+
body: beginCell()
403+
.storeUint(Opcodes.increase, 32)
404+
.storeUint(opts.queryID ?? 0, 64)
405+
.storeUint(opts.increaseBy, 32)
406+
.endCell(),
407+
});
408+
}
409+
410+
async getCounter(provider: ContractProvider) {
411+
const result = await provider.get('get_counter', []);
412+
return result.stack.readNumber();
413+
}
414+
415+
async getID(provider: ContractProvider) {
416+
const result = await provider.get('get_id', []);
417+
return result.stack.readNumber();
418+
}
419+
}
420+
421+
```
422+
423+
Then you can use this class in your react component:
424+
425+
```ts
426+
427+
import "buffer";
428+
import {
429+
TonConnectUI,
430+
useTonConnectUI,
431+
useTonWallet,
432+
} from "@tonconnect/ui-react";
433+
import {
434+
Address,
435+
beginCell,
436+
Sender,
437+
SenderArguments,
438+
storeStateInit,
439+
toNano,
440+
TonClient,
441+
} from "@ton/ton";
442+
443+
class TonConnectProvider implements Sender {
444+
/**
445+
* The TonConnect UI instance.
446+
* @private
447+
*/
448+
private readonly provider: TonConnectUI;
449+
450+
/**
451+
* The address of the current account.
452+
*/
453+
public get address(): Address | undefined {
454+
const address = this.provider.account?.address;
455+
return address ? Address.parse(address) : undefined;
456+
}
457+
458+
/**
459+
* Creates a new TonConnectProvider.
460+
* @param provider
461+
*/
462+
public constructor(provider: TonConnectUI) {
463+
this.provider = provider;
464+
}
465+
466+
/**
467+
* Sends a message using the TonConnect UI.
468+
* @param args
469+
*/
470+
public async send(args: SenderArguments): Promise<void> {
471+
// The transaction is valid for 10 minutes.
472+
const validUntil = Math.floor(Date.now() / 1000) + 600;
473+
474+
// The address of the recipient, should be in bounceable format for all smart contracts.
475+
const address = args.to.toString({ urlSafe: true, bounceable: true });
476+
477+
// The address of the sender, if available.
478+
const from = this.address?.toRawString();
479+
480+
// The amount to send in nano tokens.
481+
const amount = args.value.toString();
482+
483+
// The state init cell for the contract.
484+
let stateInit: string | undefined;
485+
if (args.init) {
486+
// State init cell for the contract.
487+
const stateInitCell = beginCell()
488+
.store(storeStateInit(args.init))
489+
.endCell();
490+
// Convert the state init cell to boc base64.
491+
stateInit = stateInitCell.toBoc().toString("base64");
492+
}
493+
494+
// The payload for the message.
495+
let payload: string | undefined;
496+
if (args.body) {
497+
// Convert the message body to boc base64.
498+
payload = args.body.toBoc().toString("base64");
499+
}
500+
501+
// Send the message using the TonConnect UI and wait for the message to be sent.
502+
await this.provider.sendTransaction({
503+
validUntil: validUntil,
504+
from: from,
505+
messages: [
506+
{
507+
address: address,
508+
amount: amount,
509+
stateInit: stateInit,
510+
payload: payload,
511+
},
512+
],
513+
});
514+
}
515+
}
516+
517+
const CONTRACT_ADDRESS = "EQAYLhGmznkBlPxpnOaGXda41eEkliJCTPF6BHtz8KXieLSc";
518+
519+
const getCounterInstance = async () => {
520+
const client = new TonClient({
521+
endpoint: "https://testnet.toncenter.com/api/v2/jsonRPC",
522+
});
523+
524+
// OR you can use createApi from @ton-community/assets-sdk
525+
// import {
526+
// createApi,
527+
// } from "@ton-community/assets-sdk";
528+
529+
// const NETWORK = "testnet";
530+
// const client = await createApi(NETWORK);
531+
532+
533+
const address = Address.parse(CONTRACT_ADDRESS);
534+
const counterInstance = client.open(Counter.createFromAddress(address));
535+
536+
return counterInstance;
537+
};
538+
539+
export const Header = () => {
540+
const [tonConnectUI, setOptions] = useTonConnectUI();
541+
const wallet = useTonWallet();
542+
543+
const increaseCount = async () => {
544+
const counterInstance = await getCounterInstance();
545+
const sender = new TonConnectProvider(tonConnectUI);
546+
547+
await counterInstance.sendIncrease(sender, {
548+
increaseBy: 1,
549+
value: toNano("0.05"),
550+
});
551+
};
552+
553+
const getCount = async () => {
554+
const counterInstance = await getCounterInstance();
555+
556+
const count = await counterInstance.getCounter();
557+
console.log("count", count);
558+
};
559+
560+
return (
561+
<main>
562+
{!wallet && (
563+
<button onClick={() => tonConnectUI.openModal()}>Connect Wallet</button>
564+
)}
565+
{wallet && (
566+
<>
567+
<button onClick={increaseCount}>Increase count</button>
568+
<button onClick={getCount}>Get count</button>
569+
</>
570+
)}
571+
</main>
572+
);
573+
};
574+
575+
```
576+
</details>
577+
578+
579+
### Wrappers for Jettons and NFTs
580+
581+
To interact with jettons or NFTs you can use [assets-sdk](https://github.com/ton-community/assets-sdk).
582+
This SDK provides wrappers that simplify interaction with these assets. For practical examples, please check our [examples](https://github.com/ton-community/assets-sdk/tree/main/examples) section.
583+
333584
## API Documentation
334585
335586
[Latest API documentation](https://ton-connect.github.io/sdk/modules/_tonconnect_ui_react.html)

0 commit comments

Comments
 (0)