Documentation
AcademyCommunitySign In
  • 👋Overview
  • 💙Platform Features
  • Getting started
    • 🚪Signing up & Logging in
      • 👤Profile Settings
    • 🎛️App Management
    • ✴️Templates to Start With
      • Basic Template (Blank app)
      • CRM Template
    • 👨‍🎓Learning Directual
      • 👨‍🏫Webinars
  • Data base
    • Data Structures
      • System Structures
    • Data Types
      • Markdown Cheat Sheet
      • Indexing Fields
      • Formatting Date/Time
    • Directual Query Language (DQL)
    • Import and Export
      • Import API
    • File Storage
      • API for File Storage
  • API and integraions
    • API-Endpoints
      • Advanced techniques for GET and POST requesting
        • Paging for GET-requests
        • Dynamic sorting for GET-requests
        • Custom filtering parameters for GET-requests
        • Advanced filtering for GET-requests
        • Formatting response for GET-request
        • Fields validation for POST-requests
        • Synchronic scenarios for POST-requests
        • Cross-Origin Resource Sharing CORS
      • API testing and debugging
      • Coding mode (raw mode) in filters
      • Swagger specification
    • Webhooks
    • Authentication API
      • Login/password
      • OpenID connect
      • Facebook oAuth
      • Google oAuth
    • Security Features
    • Other Integrations
      • OpenAI
      • Integration Hubs
        • Zapier
      • Telegram
        • Telegram: Advanced Techniques
      • Email
        • SMTP
        • Gmail
      • Twilio SMS
      • Airtable
      • Coupler.io
      • Other No-Code Tools
        • Bubble.io
          • Authorization
          • Displaying Data from Directual on Bubble
        • Adalo
        • UI bakery
        • Tilda
        • AppGyver
  • App interface
    • Web-App Builder basics
    • Web-App Settings
      • General web-app settings
      • Main menu
      • Creating a logotype
      • Web-App color scheme
      • Web-app typography
      • White Labeling
      • Web-App Icon
      • Custom Domain
      • Custom code
    • Setting Up Page Layout
      • Subpages and URL Parameters
    • Components
      • Multistep Form
      • Cards
      • Table
      • Kanban
      • Chart
      • Markdown text
      • HTML code
      • Hint
      • Link Button
      • Video
      • Form (outdated)
    • Embedding Pages
  • Scenarios
    • Understanding Directual Scenarios
      • Directual Event Model
    • Event-Based Triggers
    • Scheduled Triggers
      • Cron Format
    • Synchronous Scenarios
    • Editing Scenarios
      • System Steps
        • Start step
        • Delay step
        • Comment step
        • Catch error step
        • Link scenario step
        • Exit step
      • Action steps
        • Edit object step
        • Create object step
        • Search objects step
        • JSON step
        • Delete object step
        • Run report step
        • Generate document step
        • JS SDK step
      • Condition steps
        • Condition step
        • A/B test step
        • JS SDK condition step
      • Integration steps
        • HTTP-request step
        • Zapier step
        • Telegram step
        • API response
        • Email step
        • SQL-request step
        • Queue step
    • Using Variables
      • Global Variables
      • Context Variables (scenario parameters)
    • Testing and Debugging
    • System Scenarios
    • Advanced Scenario Settings
  • Template system
    • Templating Principles
      • Templating Techniques for Scenarios
      • Templating Techniques for Web-pages
    • Coding Mode (evaluating as a JS-expression)
    • Comparison Component
      • Regular Expressions
    • Tips for Dealing with Data
  • Telegram
    • Telegram
  • Plugins
    • 🔌Using Plugins
      • Scenario Steps Plugins
      • Web Plugins
      • User Authentication Plugins (Not Web3)
        • TMA (Telegram Mini App)
        • Google OAuth Plugin
        • Facebook OAuth Plugin
        • Open ID Auth Plugin
      • Blockchain (Web3)
        • TON (The Open Network)
        • Polygon
        • Ethereum
        • NEAR Protocol
        • NFT and Smart-Contracts
        • MetaMask Wallet
        • WalletConnect
      • WebSockets (Socket.IO)
    • 🪚Developing Plugins
      • Developing Scenario Plugins
      • Developing Web-plugins
        • Example: Using Chart.js in Directual
        • Example: Building Simple Form
        • Example: TON plugin
  • Teams
    • Teams
    • Sandbox Apps
  • JavaScript SDK
    • Directual + JavaScript SDK: The Basics
    • Internal $D Methods
    • Using Google Sheets
    • JS SDK: Examples
  • Reports
    • Reports
  • App life cycle management
    • App Versions
  • Directual 💙 React JS
    • Directual + React JS
  • Pricing and billing
    • 💳How Billing Works
    • 🎁Promo Codes
    • Pricing Plans for Apps
    • Team Pricing Plans
    • How we count requests and operations
    • On-Demand Resource Consumption
    • 🤝Affiliate Program
  • Hire a Directual expert
    • 🏆Certification
    • 🤝Matching with Experts
    • 🏦Escrow service
  • Security and stability
    • 🛡️Public Cloud
    • Platform Architecture
  • Support
    • 📬Contact Directual
  • Directual step-by-step
    • Public Development Roadmap
      • Step 0: Planning App Architecture
      • Step 1: Requesting Features
      • Step 2: Approving Features
      • Step 3. Upvoting Features
      • Step 4. Watching Features
    • Weather Forecast App
    • Web3 Marketplace on Polygon
    • Transferring NFT
Powered by GitBook
On this page
  • Component parameters
  • Component code
  • Update

Was this helpful?

  1. Plugins
  2. Developing Plugins
  3. Developing Web-plugins

Example: TON plugin

PreviousExample: Building Simple FormNextTeams

Last updated 10 months ago

Was this helpful?

Find below the code of the

Component parameters

Component code

Init

function(instance, context, config) {
  
  	// prevent double-rendering
 	if(window.init && 1 == window.init[instance.id]) return;
 	if(window.init || (window.init={}),!instance.id) return;
  	window.init[instance.id] = !0;
  
    div = $(`
	<form id="tonСonnect"></form>
	`);
  
    instance.canvas.append(div);
}

Update

function(instance, properties, context, config) {  
    $form = $("#tonСonnect");

    // clear layout on update
    var layout = $('#tonСonnect')
    layout.empty();  

    var locale = config.locale || 'ENG'

    // local templating
    function template(input) {
        const templateData = _.get(context,"endpoint[0]") || {};
        _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
        if (!templateData) return ""
        const renderTemplate = (template) => {
            return _.template(template, {
                interpolate: /{{([\s\S]+?)}}/g
            })(templateData, {
                variable: '',
                evaluate: /<%([\s\S]+?)%>/g,
                escape: /<%-([\s\S]+?)%>/g
            });
        };
        try {
            const result = renderTemplate(input);
            return result;
        } catch (error) {
            console.error("template")
            console.error(input)
            console.error(templateData)
            console.error('Error rendering template:', error);
            return '';
        }
    }

    var dict = {
        ENG: {
            "disconnect": "Disconnect wallet",
            "confirm": "Confirm transaction",
            "connect": "Connect wallet",
            "successMessage": "Success! The transaction may take a few minutes.",
        },
        GER: {
            "disconnect": "Wallet trennen",
            "confirm": "Transaktion bestätigen",
            "connect": "Wallet verbinden",
            "successMessage": "Erfolg! Die Transaktion kann einige Minuten dauern.",
        },
        ESP: {
            "disconnect": "Desconectar cartera",
            "confirm": "Confirmar transacción",
            "connect": "Conectar cartera",
            "successMessage": "¡Éxito! La transacción puede tardar unos minutos.",
        },
        FRA: {
            "disconnect": "Déconnecter le portefeuille",
            "confirm": "Confirmer la transaction",
            "connect": "Connecter le portefeuille",
            "successMessage": "Succès ! La transaction peut prendre quelques minutes.",
        },
        RUS: {
            "disconnect": "Отключить кошелек",
            "confirm": "Подтвердить транзакцию",
            "connect": "Подключить кошелек",
            "successMessage": "Успех! Транзакция может занять несколько минут.",
        },
        JPN: {
            "disconnect": "ウォレットを切断",
            "confirm": "取引を確認する",
            "connect": "ウォレットを接続",
            "successMessage": "成功です!取引には数分かかる場合があります。",
        },
        POR: {
            "disconnect": "Desconectar carteira",
            "confirm": "Confirmar transação",
            "connect": "Conectar carteira",
            "successMessage": "Sucesso! A transação pode levar alguns minutos.",
        },
        IND: {
            "disconnect": "वॉलेट डिस्कनेक्ट करें",
            "confirm": "लेन-देन की पुष्टि करें",
            "connect": "वॉलेट कनेक्ट करें",
            "successMessage": "सफलता! लेन-देन में कुछ मिनट लग सकते हैं।"
        },
        KOR: {
            "disconnect": "지갑 연결 끊기",
            "confirm": "거래 확인",
            "connect": "지갑 연결",
            "successMessage": "성공! 거래가 몇 분 정도 걸릴 수 있습니다.",
        }
    }

    var svgData = `<g id="ton-logo" fill="#FFFFFF" fill-rule="nonzero">
<path d="M37.1153287,19 C38.7084887,19 40,20.2846058 40,21.8692473 L40,60.125878 
C40,63.0535566 36.1095077,64.1011762 34.6246277,61.5733414 C32.2779476,57.5783927 
32.2779476,57.5783927 25.2379073,45.5935466 C20.3312126,37.240472 18.8443354,34.7092373 
17.5679538,32.5319622 L17.2376495,31.9684115 C16.7979832,31.218129 16.3500203,30.4531462 
15.7587094,29.4433688 C15.2208728,28.3670775 14.9605279,27.179804 15.0048455,25.9969387 
C15.0433928,24.8019799 15.3833303,23.6308115 15.9880796,22.6050914 C16.5924637,21.5736398 
17.443754,20.7075471 18.4800157,20.0713338 C19.4987828,19.4520827 20.6548433,19.0879541 
22.0458062,19 L37.1153287,19 Z M23.0700308,24.0026041 L22.4228731,24 C22.1604706,24.0186412 
21.9105713,24.1008057 21.7049058,24.231268 C21.4909167,24.3684171 21.3177649,24.5523074 
21.1922318,24.7759213 C21.0751474,24.9832245 21.008859,25.2216226 21.0009575,25.4761216 
C20.9924828,25.7124407 21.042561,25.9508345 21.0607339,26.0035974 C21.6607738,27.0699046 
22.1019795,27.8539541 22.5525285,28.654607 L22.8561242,29.194115 C24.0393632,31.2968024 
25.5276974,33.9416626 30.1280032,42.116685 C31.7281095,44.9601711 32.9517202,47.1346016 
33.9169516,48.8498763 L34,49 L34,24.0028938 L23.2616773,24.0032932 C23.1986199,24.0030773 
23.1350331,24.0028478 23.0700308,24.0026041 Z" id="Path"></path>
<path d="M51.0418462,19.0032931 C51.1232812,19.0035127 51.2059707,19.0037469 51.2910421,19.0039966 
L52.1514281,19.0066926 C53.3455002,19.0879541 54.5015812,19.4520827 55.5313829,20.0780638 
C56.5566466,20.7075471 57.4079519,21.5736399 58.0084415,22.5984473 C58.6171068,23.6308116 
58.9570504,24.80198 58.9950845,25.9821942 C59.0401209,27.1852586 58.7771527,28.3769796 58.1455257,
29.6135309 C57.7314831,30.3185218 57.3905069,30.8991026 57.0710208,31.4430922 L56.7567879,31.9781372 
C55.4095976,34.2720005 54.1431145,36.4284435 48.7605616,45.5933259 C41.7218386,57.5781722 41.7218386,
57.5781722 39.3755976,61.573121 C37.8908494,64.1012045 34,63.0536927 34,60.1258786 L34,21.8692473 C34,
20.2846058 35.2915342,19 36.8847225,19 L51.0418462,19.0032931 Z M40,49 L40.0883486,48.8500819 C41.0529283,
47.1346086 42.275713,44.9599264 43.8747391,42.1161111 C48.8716956,33.2291885 50.1944193,30.8767678 
51.4119971,28.7158234 L51.7040243,28.1976254 C52.0466313,27.5897724 52.4033802,26.9571476 52.8526196,
26.1605091 C52.9585278,25.9417484 53.007886,25.7081133 52.9989778,25.4585291 C52.991576,25.2188698 
52.9253188,24.9804442 52.8045189,24.7664166 C52.6828154,24.5494772 52.509745,24.3655656 52.306493,
24.2351875 C52.0902878,24.0979233 51.8405061,24.0157492 51.7683482,24.0038551 L40,24 L40,49 Z" id="Path"></path>
<path d="M37.0000346,0 C57.4362074,0 74,16.5638158 74,37.0000346 C74,57.4361958 57.4361958,74 37.0000346,
74 C16.5638158,74 0,57.4362074 0,37.0000346 C0,16.5638042 16.5638042,0 37.0000346,0 Z M37.5000348,5 
C20.1013601,5 6,19.1013601 6,36.5000348 C6,53.8986497 20.10137,68 37.5000348,68 C54.8986399,68 69,53.8986399 69,
36.5000348 C69,19.10137 54.8986497,5 37.5000348,5 Z" id="Path"></path>
</g>`
    const accentTextColor = getComputedStyle(document.documentElement)
    .getPropertyValue('--button-accent-text').trim();
    svgData = svgData.replace(/fill="#FFFFFF"/g, `fill="${accentTextColor}"`);

    var connect = $(`
<button class='tonConnectPlugin_button'>
<svg transform="translate(-5 0)"  width="22px" height="22px" viewBox="0 0 74 74" 
version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">${svgData}</svg>&nbsp;
${dict[locale].connect}
</button>`);

    // add styling:
    var style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = `
.tonConnectPlugin_button {
background-color: var(--button-accent-bgr);
color: var(--button-accent-text);
border: solid 1px var(--button-accent-border);
display: flex;
user-select: none;
justify-content: center;
align-items: center;
padding: 1px 18px;
text-decoration: none;
font-size: var(--text-font-size);
border-radius: var(--border-radius);
cursor: pointer;
outline: none;
transition: 0s;
white-space: nowrap;
font-weight: var(--text-font-weight);
margin: 1px;
height:42px;
}
.tonConnectPlugin_button:hover {
background-color: var(--button-accent-hover-bgr);
color: var(--button-accent-hover-text);
border-color: var(--button-accent-hover-border);
box-shadow: 0 0 0 1px var(--button-accent-hover-border);
}
.tonConnectPlugin_button:active {
background-color: var(--button-accent-active-bgr);
color: var(--button-accent-active-text);
border-color: var(--button-accent-active-border);
box-shadow: 0 0 0 1px var(--button-accent-active-border);
}
.tonConnectPlugin_icon {
width: 22px;
margin-right:5px;
}
.tonConnectPlugin_disconenct {
font-size: 14px;
color:var(--layout-accent);
text-decoration:none;
}
.tonConnectPlugin_disconenct:hover {
color:var(--layout-accent-hover);
}
.tonConnectPlugin_wallet {
display: flex;
gap: 0 16px;
background:var(--cards-bgr);
border-radius: 20px;
padding: 12px;
margin-bottom: 12px;
}
.tonConnectPlugin_wallet_info {
flex: 1;
overflow:hidden;
text-overflow: ellipsis;
}
.wallet_img {
width: 75px;
height: 75px;
overflow: hidden;
border-radius: 100%;
flex-shrink: 0;
}
.wallet_title {
font-weight: bold;
margin-bottom:5px;
}
.wallet_description {
opacity:.5;
overflow:hidden;
text-overflow: ellipsis;
margin-bottom:5px;
}
.tonConnectPlugin_pay {
display: flex;
gap: 0 16px;
align-items: center;
font-size: var(--h3-font-size);
cursor: pointer;
}
.tonConnectPlugin_success {
background-color: var(--hint-ok-light);
border-left: solid 5px var(--hint-ok);
color: var(--hint-text-color);
padding: 18px;
font-size: var(--text-font-size);
position: relative;
border-radius: 4px;
}
`;
    document.getElementsByTagName('head')[0].appendChild(style);

    connect.click((e) => {
        e.preventDefault()
        e.stopPropagation()
        config.tonConnectUI.openModal()
    })

    // success message
    var success = document.createElement('blockquote');
    success.className = 'tonConnectPlugin_success';
    success.innerHTML = dict[locale].successMessage;
    
    // Create the displayWallet container
    var displayWallet = document.createElement('div');
    displayWallet.className = 'tonConnectPlugin_wallet';

    var displayWalletInfo = document.createElement('div');
    displayWalletInfo.className = 'tonConnectPlugin_wallet_info';

    // Create the image element and set its src attribute
    var imgElement = document.createElement('img');
    imgElement.className = 'wallet_img';
    imgElement.src = _.get(config,"wallet.imageUrl");

    // Create the title div and set its innerHTML
    var titleElement = document.createElement('div');
    titleElement.className = 'wallet_title';
    titleElement.innerHTML = _.get(config,"wallet.name");

    // Create the description div and set its innerHTML
    var descriptionElement = document.createElement('div');
    descriptionElement.className = 'wallet_description';
    descriptionElement.innerHTML = _.get(config,"wallet.account.address");

    var disconnectButton =  document.createElement('a') //$(`<a class="tonConnectPlugin_disconenct">Disconnect wallet</a>`);
    disconnectButton.className = 'wallet_description';
    disconnectButton.innerHTML = dict[locale].disconnect
    disconnectButton.href = "#"; // Optionally, set the href attribute to '#' to make it clickable
    disconnectButton.addEventListener('click', function(e) {
        e.preventDefault(); // Prevent the default action if necessary
        config.tonConnectUI.disconnect(); // Call the disconnect function
    });

    // Append the elements to the displayWallet container
    displayWallet.appendChild(imgElement);
    displayWalletInfo.appendChild(titleElement);
    displayWalletInfo.appendChild(descriptionElement);
    displayWalletInfo.appendChild(disconnectButton);
    displayWallet.appendChild(displayWalletInfo);

    var tonMulti = 1000000000
    var amount = (template(_.get(context,"amount") || 0)/tonMulti).toFixed(2)

    var address = template(_.get(context,"address"))
    var orderNumber = template(_.get(context,"orderNumber")) || Math.floor(Math.random()*100000000)

    var send = $(`<div class="tonConnectPlugin_pay">
<div class="tonConnectPlugin_amount"><b>${amount}</b> TONs</div>
<button class='tonConnectPlugin_button'>${dict[locale].confirm}</button>
</div>`);

    const sendNotification = () => {
  
        var payload = {
            user: _.get(config,"auth.user"),
            addressFrom: _.get(config,"wallet.account.address"),
            addressTo: address,
            orderNumber: orderNumber,
            status: "success",
            amountTons: amount,
            amountNanoTons: amount * tonMulti
        }
        if (!_.get(context,"webhook")) {
            console.log("TON PLUGIN: no webhook")
            return;
        }
        fetch(_.get(context,"webhook"), {
            mode:  'cors', 
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(payload)
        }).then(()=>{
            console.log("TON PLUGIN: message to the webhook is sent")
        })
    }


    send.click((e)=>{
        e.preventDefault()
        e.stopPropagation()
        if (!address) {
            alert('TON: no address to send');
            return;
        }
        if (!template(_.get(context,"amount"))) {
            alert('TON: transaction amount = 0');
            return;
        }
        var message = config.beginCell()
        .storeUint(0, 32) // write 32 zero bits to indicate that a text comment will follow
        .storeStringTail(`Order #${orderNumber}`) 
        .endCell();
        var tx = {
            // The transaction is valid for 10 minutes from now, in unix epoch seconds.
            validUntil: Math.floor(Date.now() / 1000) + 600,
            messages: [
                {
                    address: address,
                    // Amount to send in nanoTON. For example, 0.005 TON is 5000000 nanoTON.
                    amount: amount * tonMulti,
                    payload: message.toBoc().toString("base64"),
                    bounce:false
                },
            ],
        };
        console.log("TON PLUGIN: tx")
        console.log(tx)
        config.tonConnectUI.sendTransaction(tx)
            .then((res)=>{ 
                sendNotification();
            	layout.empty();  
             	$form.append(success)
            })
            .catch((err)=>{ alert('error') })
        e.preventDefault()
    })

    // adding the controls:
    if(config.wallet) { 
        $form.append(displayWallet);
        $form.append(send);
    } else {
        $form.append(connect);
    }
}

Destroy

function destroy(instance) {
  if(window.init && window.init[instance.id] == true){
		delete window.init[instance.id];
  }
}
🪚
TON plugin