Skip to content

Restrictions Guide

This restrictions guide assumes that you have already completed the TheM>Getting Started>Quick Start guide and are familiar with TheM class, TheM submodule initialization, and creating/listening for custom events. This guide also assumes that you have already installed the amplifi_mobile_sdk package into your project and placed the following minified libraries in the /lib folder of your project: axios.min.js (Optional - fetch will be used if axios is not present), crypto-js.min.js, lz-string.min.js, moment.min.js, and socket.io.min.js. In addition, you should have completed the Onboarding Guide tutorial in order to create and onboard a user which can be logged into your ampliFi instance and the Beneficiaries Guide tutorial so that your user has at least one beneficiary for testing allowed transactions.

Restrictions consist of both system-wide restrictions that apply to all users and user specific restrictions which are applied to transactions based on the current user. When a transaction is verified using TheM.restrictions, rules are sorted by priority and then applied one-by-one. The last applicable rule will overwrite previously applied rules if a conflict exists. However, if a restriction contains the isIgnoreRest: true property, any remaining unapplied rules will be ignored. See the ampliFi MODULES Restrictions documentation for more details regarding possible restriction properties.

1. In the src folder of your project (from the Quick Start guide of the TheM Getting Started section), create a new file called restrictions.js with the following code.

restrictions.js

import ClassTheM from "../node_modules/@PayGearsCorp/amplifi_mobile_sdk/TheM/them.mjs";

import { thisDevice } from "./android-demo-device.js"; //android device emulator for testing

const AMPLIFI_BASE_URL = "PUT_YOUR_INSTANCE_URL_HERE"; //Speak to a support representative to be issued a sandbox instance URL
const AMPLIFI_CORE_URL = `${AMPLIFI_BASE_URL}core/`;
const DEVICE_TAG = "PUT_YOUR_DEVICE_TAG_HERE"; //Use deviceTag obtained from onboarding tutorial for this device

const subClassesToInit = [
    "accounts",
    "beneficiaries",
    "cards",
    //"cheques",
    "common",
    //"externalAccounts",
    //"fdrs",
    //"fundstransfer",
    //"fxrates",
    //"genericRequests",
    //"ious",
    //"onboarding",
    //"payees",
    //"remittance",
    "restrictions",
    //"statics",
    "user"
];


export const restrictionsTutorial = async (subClasses = "") => {
    TheM = new ClassTheM({
        config: {
            AFiInstanceId: "test",
            modulesFolder: "",
            modulesFolderOnboarding: "",
            webworkerFolder: "../TheM/",
            baseLibURL: "../demo/lib/",
            backEndURL: AMPLIFI_CORE_URL,
            socketURL: AMPLIFI_BASE_URL,
        },
        libs: {
        }
    });

    //Emulate user device before initializing TheM submodules
    TheM.thisDevice = {
        ...thisDevice,
        TheM,
        deviceTag: DEVICE_TAG,
    };

    //Initialize desired submodules
    //Some modules depend on others so must be initialized together
    //For instance, most submodules require the "common" subclass to be initialized
    await TheM.doInit(subClasses);

    //restrictions workflow to try
    //Uncomment to run the whole workflow or follow the instructions in the browser
    /*
    //Prepare for logging in
    //Log in using the instructions in the browser or use the doAuthenticate method from the device emulator we created during onboarding
    await TheM.thisDevice.doAuthenticate(DEVICE_TAG);

    //Make sure necessary submodules are updated and ready
    await TheM.accounts.doUpdate(true);
    console.log(`TheM.accounts.isReady: ${JSON.stringify(TheM.accounts.isReady)} - We will use this submodule to set the sourceAccount to check if an example transaction isAllowed`);
    await TheM.beneficiaries.doUpdate(true);
    console.log(`TheM.beneficiaries.isReady: ${JSON.stringify(TheM.beneficiaries.isReady)} - We will use this submodule to set the destinationAccount to check if an example transaction isAllowed`);

    //Pull fresh restrictions data from the server and check to make sure the restrictions submodule is ready
    await TheM.restrictions.doUpdate(true);
    console.log(`TheM.restrictions.isReady: ${JSON.stringify(TheM.restrictions.isReady)}`);

    //TheM.restrictions properties and methods to try
    console.log(`TheM.restrictions.accountsAsDestinationFor("USA"): ${JSON.stringify(TheM.restrictions.accountsAsDestinationFor("USA"))}`);
    console.log(`TheM.restrictions.accountsAsSourceFor("USA"): ${JSON.stringify(TheM.restrictions.accountsAsSourceFor("USA"))}`);
    console.log(`TheM.restrictions.currenciesAllowed("USA"): ${JSON.stringify(TheM.restrictions.currenciesAllowed("USA"))}`);
    console.log(`TheM.restrictions.isCurrencyAllowed("USA", "USD"): ${JSON.stringify(TheM.restrictions.isCurrencyAllowed("USA", "USD"))}`);
    console.log(`TheM.restrictions.canAccountBeSource("USA", "Standard"): ${JSON.stringify(TheM.restrictions.canAccountBeSource("USA", "Standard"))}`);
    console.log(`TheM.restrictions.restriction("USA"): ${JSON.stringify(TheM.restrictions.restriction("USA"))}`);
    console.log(`TheM.restrictions.filtered({ isAllowed: true }): ${JSON.stringify(TheM.restrictions.filtered({ isAllowed: true }))}`);
    console.log(`TheM.restrictions.one("USA"): ${JSON.stringify(TheM.restrictions.one("USA"))}`);
    console.log(`TheM.restrictions.all: ${JSON.stringify(TheM.restrictions.all)}`);


    const sampleTransaction = {
        sourceAccount: TheM.accounts[0],
        destinationAccount: TheM.beneficiaries[0],
        txnType: TheM.beneficiaries[0].txnType,
        transactionTypeId: TheM.beneficiaries[0].txnType,
        sourceAccountCurrency: TheM.accounts[0].currency,
        destinationAccountCurrency: TheM.accounts[0].currency,
        currency: TheM.accounts[0].currency,
        amount: 10.01
    };

    //Test the sample transaction to see if TheM.restrictions would allow it
    const isAllowedResult = await TheM.restrictions.isAllowed(sampleTransaction);

    if (isAllowedResult.isAllowed) {
        console.log("The sample transaction is allowed!");
        console.log(JSON.stringify(sampleTransaction));
    } else {
        console.log("The sample transaction is not allowed.")
    }

    console.log(JSON.stringify(isAllowedResult));

    //Logout when finished
    //await TheM.user.doLogout();
    */
};

await restrictionsTutorial(subClassesToInit.join(" "));

2. The restrictions module expects the user to be using some type of device so make sure the android-demo-device.js file used during onboarding is still in your /src folder.

3. Create a new file in the /demo folder of your project called restrictions.html with the following code.

restrictions.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />

    <title>ampliFi</title>

    <script>
        var TheM;
        var TheM_config;
    </script>

    <script src="../lib/socket.io.min.js"></script>
    <script src="../lib/lz-string.min.js"></script>
    <script src="../lib/moment.min.js"></script>
    <script src="../lib/axios.min.js"></script>
    <script src="../lib/crypto-js.min.js"></script>
    <script type="module" src="/../src/restrictions.js"></script>

    <style>
        html {
            color: white;
            background-color: black;
        }
    </style>
</head>


<body>
    <div>
        Hit F12 to open the browser console.
        Start working with TheM by typing "TheM" into the browser console.
    </div>
    <br />
    <br />
    <div>
        1. In order to log a user in, we will need to prepare the user credentials using the encryptedServerSecret
        stored locally during onboarding. Type the following to retrieve the encryptedServerSecret. (Or skip steps 1-5
        by using the doAuthenticate method in the device emulator like so, `await
        TheM.thisDevice.doAuthenticate(DEVICE_TAG);`.)
        <br /><br />
        <code>let { encryptedServerSecret } = await TheM.thisDevice.retrieveLocally("encryptedServerSecret", true);</code>
        <br /><br />
        Type <code>encryptedServerSecret</code> into the browser console and hit enter to view the encryptedServerSecret
        value.
        <br /><br />
        2. Since we are using an emulated android device to log in, we need to get the cryptotext value like so.
        <br /><br />
        <code>
            let _SUPER_SECRET = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";<br />
            let _dtsValueString = (new Date()).valueOf().toString();<br />
            let serverSecret = CryptoJS.AES.decrypt(encryptedServerSecret, _SUPER_SECRET).toString(CryptoJS.enc.Utf8);<br />
            let cryptotext = CryptoJS.AES.encrypt((TheM.thisDevice.deviceTag) + _dtsValueString, serverSecret).toString(); 
        </code>
        <br /><br />
        3. Set a socket connection for bidirectional communication.
        <br /><br />
        <pre><code>TheM.thisDevice.halfRef = TheM.common.GetRandomSTR(40);<br />let manager = new TheM.io.Manager(TheM.config.socketURL + "?halfRef=" + TheM.thisDevice.halfRef, {<br />  autoConnect: false<br />});<br />let socket = manager.socket("/");</code></pre>
        <br />
        4. Open the socket connection.
        <br /><br />
        <pre><code>manager.connect(function (data) {<br />  console.log("established real-time comm channel for onboarding");<br />  TheM.thisDevice.isRealTimeCommAvailable = true;<br />});</code></pre>
        <br />
        5. Log the user in using the deviceTag obtained during onboarding and the newly created cryptotext.
        <br /><br />
        <pre><code>const credentials = {<br />  "dtsValueString": _dtsValueString,<br />  "deviceTag": "PUT_DEVICE_TAG_HERE",<br />  "deviceData": TheM.thisDevice.data,<br />  "channel": TheM.thisDevice.platform,<br />  "dynamicScreensVersion": TheM.thisDevice.dynamicScreensVersion,<br />  "socket": {<br />    halfRef: TheM.thisDevice.halfRef<br />  },<br />  "pushMessToken": TheM.thisDevice.pushMessToken,<br />  "cryptotext": cryptotext<br />};<br />await TheM.user.doLogin(credentials);</code></pre>
        <br />
        6. After authentication, the locally stored data should be automatically loaded. Make sure the following
        submodules are updated and ready.
        <br /><br />
        <code>await TheM.accounts.doUpdate(true);<br />TheM.accounts.isReady; //{JSON.stringify(TheM.accounts.isReady)} - We will use this submodule to set the sourceAccount to check if an example transaction isAllowed.<br /></code>
        <code>await TheM.beneficiaries.doUpdate(true);<br />TheM.beneficiaries.isReady; //We will use this submodule to set the destinationAccount to check if an example transaction isAllowed.<br /></code>
        <code>await TheM.restrictions.doUpdate(true);<br />TheM.restrictions.isReady;<br /></code>
        <br /><br />
        7. Get a list of accounts that can be a destinationAccount for the given txnType.
        <br /><br />
        <code>TheM.restrictions.accountsAsDestinationFor("USA");</code>
        <br /><br />
        8. Get a list of accounts that can be a sourceAccount for the given txnType.
        <br /><br />
        <code>TheM.restrictions.accountsAsSourceFor("USA");</code>
        <br /><br />
        9. Get a list of allowed currencies for the given txnType.
        <br /><br />
        <code>TheM.restrictions.currenciesAllowed("USA");</code>
        <br /><br />
        10. Check if the given currency is allowed for the given txnType.
        <br /><br />
        <code>TheM.restrictions.isCurrencyAllowed("USA", "USD");</code>
        <br /><br />
        11. Check if the given account type can be a sourceAccount for the given txnType.
        <br /><br />
        <code>TheM.restrictions.canAccountBeSource("USA", "Standard");</code>
        <br /><br />
        12. Get a restriction based on a given txnType.
        <br /><br />
        <code>TheM.restrictions.restriction("USA");</code>
        <br /><br />
        13. Get a list of restrictions filtered by given key:value pairs.
        <br /><br />
        <code>TheM.restrictions.filtered({ isAllowed: true });</code>
        <br /><br />
        14. Get the first restriction specific to the given txnType.
        <br /><br />
        <code>TheM.restrictions.one("USA");</code>
        <br /><br />
        15. Get a list of all restrictions that may be applicable to the user.
        <br /><br />
        <code>TheM.restrictions.all;</code>
        <br /><br />
        16. Define a sample transaction for testing the .isAllowed method of TheM.restrictions.
        <br />
        <pre><code>const sampleTransaction = {<br />  sourceAccount: TheM.accounts[0],<br />  destinationAccount: TheM.beneficiaries[0],<br />  txnType: TheM.beneficiaries[0].txnType,<br />  transactionTypeId: TheM.beneficiaries[0].txnType,<br />  sourceAccountCurrency: TheM.accounts[0].currency,<br />  destinationAccountCurrency: TheM.accounts[0].currency,<br />  currency: TheM.accounts[0].currency,<br />  amount: 10.01<br />};</code></pre>
        <br />
        17. Test the sample transaction.
        <br /><br />
        <code>const isAllowedResult = await TheM.restrictions.isAllowed(sampleTransaction);<br />console.log(JSON.stringify(isAllowedResult));</code>
        <br /><br />
        18. Keep exploring TheM.restrictions properties and methods and log out when finished.
        <br /><br />
        <code>
            await TheM.user.doLogout();
        </code>
        <br /><br />
    </div>
</body>

</html>

4. Start a server in the root folder of your project.

py -m http.server 8000

5. Open a browser and enter the following URL: http://localhost:8000/demo/

6. Click on the link for "restrictions.html" and follow the instructions to log in, test TheM.restriction properties and methods, and log out.