/** * Sync the wallet's data */ tABC_CC ABC_WalletSyncData(tABC_WalletID self, int *pDirty, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; ABC_SET_ERR_CODE(pError, ABC_CC_Ok); tABC_GeneralInfo *pInfo = NULL; char *szDirectory = NULL; char *szSyncDirectory = NULL; tWalletData *pData = NULL; bool bExists = false; bool bNew = false; // Fetch general info ABC_CHECK_RET(ABC_GeneralGetInfo(&pInfo, pError)); // create the wallet root directory if necessary ABC_CHECK_RET(ABC_WalletCreateRootDir(pError)); // create the wallet directory - <Wallet_UUID1> <- All data in this directory encrypted with MK_<Wallet_UUID1> ABC_CHECK_RET(ABC_WalletGetDirName(&szDirectory, self.szUUID, pError)); ABC_CHECK_RET(ABC_FileIOFileExists(szDirectory, &bExists, pError)); if (!bExists) { ABC_CHECK_RET(ABC_FileIOCreateDir(szDirectory, pError)); } // create the wallet sync dir under the main dir ABC_CHECK_RET(ABC_WalletGetSyncDirName(&szSyncDirectory, self.szUUID, pError)); ABC_CHECK_RET(ABC_FileIOFileExists(szSyncDirectory, &bExists, pError)); if (!bExists) { ABC_CHECK_RET(ABC_FileIOCreateDir(szSyncDirectory, pError)); // Init repo ABC_CHECK_RET(ABC_SyncMakeRepo(szSyncDirectory, pError)); bNew = true; } // load the wallet data into the cache ABC_CHECK_RET(ABC_WalletCacheData(self, &pData, pError)); ABC_CHECK_ASSERT(NULL != pData->szWalletAcctKey, ABC_CC_Error, "Expected to find RepoAcctKey in key cache"); // Sync ABC_CHECK_RET(ABC_SyncRepo(pData->szWalletSyncDir, pData->szWalletAcctKey, pDirty, pError)); if (*pDirty || bNew) { *pDirty = 1; ABC_CHECK_RET(ABC_WalletClearCache(pError)); } exit: ABC_FREE_STR(szSyncDirectory); ABC_FREE_STR(szDirectory); ABC_GeneralFreeInfo(pInfo); return cc; }
/** * Load the general info. * * This function will load the general info which includes information on * Obelisk Servers, AirBitz fees and miners fees. */ tABC_CC ABC_GeneralGetInfo(tABC_GeneralInfo **ppInfo, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; json_t *pJSON_Root = NULL; json_t *pJSON_Value = NULL; char *szInfoFilename = NULL; tABC_GeneralInfo *pInfo = NULL; json_t *pJSON_MinersFeesArray = NULL; json_t *pJSON_AirBitzFees = NULL; json_t *pJSON_ObeliskArray = NULL; json_t *pJSON_SyncArray = NULL; bool bExists = false; ABC_CHECK_NULL(ppInfo); // get the info filename ABC_CHECK_RET(ABC_GeneralGetInfoFilename(&szInfoFilename, pError)); // check to see if we have the file ABC_CHECK_RET(ABC_FileIOFileExists(szInfoFilename, &bExists, pError)); if (false == bExists) { // pull it down from the server ABC_CHECK_RET(ABC_GeneralUpdateInfo(pError)); } // load the json ABC_CHECK_RET(ABC_FileIOReadFileObject(szInfoFilename, &pJSON_Root, true, pError)); // allocate the struct ABC_NEW(pInfo, tABC_GeneralInfo); // get the miners fees array pJSON_MinersFeesArray = json_object_get(pJSON_Root, JSON_INFO_MINERS_FEES_FIELD); ABC_CHECK_ASSERT((pJSON_MinersFeesArray && json_is_array(pJSON_MinersFeesArray)), ABC_CC_JSONError, "Error parsing JSON array value"); // get the number of elements in the array pInfo->countMinersFees = (unsigned int) json_array_size(pJSON_MinersFeesArray); if (pInfo->countMinersFees > 0) { ABC_ARRAY_NEW(pInfo->aMinersFees, pInfo->countMinersFees, tABC_GeneralMinerFee*); }
/** * Loads the settings for a specific account using the given key * If no settings file exists for the given user, defaults are created * * @param login Access to the account sync dir * @param ppSettings Location to store ptr to allocated settings (caller must free) * @param pError A pointer to the location to store the error if there is one */ tABC_CC ABC_AccountSettingsLoad(const Login &login, tABC_AccountSettings **ppSettings, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; AutoCoreLock lock(gCoreMutex); tABC_AccountSettings *pSettings = NULL; json_t *pJSON_Root = NULL; json_t *pJSON_Value = NULL; bool bExists = false; auto filename = login.syncDir() + ACCOUNT_SETTINGS_FILENAME; ABC_CHECK_NULL(ppSettings); ABC_CHECK_RET(ABC_FileIOFileExists(filename.c_str(), &bExists, pError)); if (true == bExists) { // load and decrypted the file into a json object ABC_CHECK_RET(ABC_CryptoDecryptJSONFileObject(filename.c_str(), toU08Buf(login.dataKey()), &pJSON_Root, pError)); //ABC_DebugLog("Loaded settings JSON:\n%s\n", json_dumps(pJSON_Root, JSON_INDENT(4) | JSON_PRESERVE_ORDER)); // allocate the new settings object ABC_NEW(pSettings, tABC_AccountSettings); pSettings->szFirstName = NULL; pSettings->szLastName = NULL; pSettings->szNickname = NULL; // get the first name pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_FIRST_NAME_FIELD); if (pJSON_Value) { ABC_CHECK_ASSERT(json_is_string(pJSON_Value), ABC_CC_JSONError, "Error parsing JSON string value"); ABC_STRDUP(pSettings->szFirstName, json_string_value(pJSON_Value)); } // get the last name pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_LAST_NAME_FIELD); if (pJSON_Value) { ABC_CHECK_ASSERT(json_is_string(pJSON_Value), ABC_CC_JSONError, "Error parsing JSON string value"); ABC_STRDUP(pSettings->szLastName, json_string_value(pJSON_Value)); } // get the nickname pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_NICKNAME_FIELD); if (pJSON_Value) { ABC_CHECK_ASSERT(json_is_string(pJSON_Value), ABC_CC_JSONError, "Error parsing JSON string value"); ABC_STRDUP(pSettings->szNickname, json_string_value(pJSON_Value)); } pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_PIN_FIELD); if (pJSON_Value) { ABC_CHECK_ASSERT(json_is_string(pJSON_Value), ABC_CC_JSONError, "Error parsing JSON string value"); ABC_STRDUP(pSettings->szPIN, json_string_value(pJSON_Value)); } // get name on payments option pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_NAME_ON_PAYMENTS_FIELD); ABC_CHECK_ASSERT((pJSON_Value && json_is_boolean(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON boolean value"); pSettings->bNameOnPayments = json_is_true(pJSON_Value) ? true : false; // get minutes auto logout pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_MINUTES_AUTO_LOGOUT_FIELD); ABC_CHECK_ASSERT((pJSON_Value && json_is_integer(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON integer value"); pSettings->minutesAutoLogout = (int) json_integer_value(pJSON_Value); pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_RECOVERY_REMINDER_COUNT); if (pJSON_Value) { ABC_CHECK_ASSERT((pJSON_Value && json_is_integer(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON integer value"); pSettings->recoveryReminderCount = (int) json_integer_value(pJSON_Value); } else { pSettings->recoveryReminderCount = 0; } // get language pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_LANGUAGE_FIELD); ABC_CHECK_ASSERT((pJSON_Value && json_is_string(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON string value"); ABC_STRDUP(pSettings->szLanguage, json_string_value(pJSON_Value)); // get currency num pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_NUM_CURRENCY_FIELD); ABC_CHECK_ASSERT((pJSON_Value && json_is_integer(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON integer value"); pSettings->currencyNum = (int) json_integer_value(pJSON_Value); // get advanced features pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_ADVANCED_FEATURES_FIELD); ABC_CHECK_ASSERT((pJSON_Value && json_is_boolean(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON boolean value"); pSettings->bAdvancedFeatures = json_is_true(pJSON_Value) ? true : false; pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_DAILY_SPEND_LIMIT_ENABLED); if (pJSON_Value) { ABC_CHECK_ASSERT((pJSON_Value && json_is_boolean(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON boolean value"); pSettings->bDailySpendLimit = json_is_true(pJSON_Value) ? true : false; } else { pSettings->bDailySpendLimit = false; } pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_DAILY_SPEND_LIMIT_SATOSHIS); if (pJSON_Value) { ABC_CHECK_ASSERT((pJSON_Value && json_is_integer(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON daily spend satoshi value"); pSettings->dailySpendLimitSatoshis = (int64_t) json_integer_value(pJSON_Value); } else { pSettings->dailySpendLimitSatoshis = 0; } pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_SPEND_REQUIRE_PIN_ENABLED); if (pJSON_Value) { ABC_CHECK_ASSERT((pJSON_Value && json_is_boolean(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON boolean value"); pSettings->bSpendRequirePin = json_is_true(pJSON_Value) ? true : false; } else { // Default to PIN required pSettings->bSpendRequirePin = true; } pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_DISABLE_PIN_LOGIN); if (pJSON_Value) { ABC_CHECK_ASSERT((pJSON_Value && json_is_boolean(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON boolean value"); pSettings->bDisablePINLogin = json_is_true(pJSON_Value) ? true : false; } else { // Default to PIN login allowed pSettings->bDisablePINLogin = false; } pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_PIN_LOGIN_COUNT); if (pJSON_Value) { ABC_CHECK_ASSERT((pJSON_Value && json_is_integer(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON pin login count"); pSettings->pinLoginCount = json_integer_value(pJSON_Value); } else { // Default to PIN login allowed pSettings->pinLoginCount = 0; } pJSON_Value = json_object_get(pJSON_Root, JSON_ACCT_SPEND_REQUIRE_PIN_SATOSHIS); if (pJSON_Value) { ABC_CHECK_ASSERT((pJSON_Value && json_is_integer(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON daily spend satoshi value"); pSettings->spendRequirePinSatoshis = (int64_t) json_integer_value(pJSON_Value); } else { // Default PIN requirement to 50mb pSettings->spendRequirePinSatoshis = DEF_REQUIRE_PIN_SATOSHIS; } // get the denomination object json_t *pJSON_Denom = json_object_get(pJSON_Root, JSON_ACCT_BITCOIN_DENOMINATION_FIELD); ABC_CHECK_ASSERT((pJSON_Denom && json_is_object(pJSON_Denom)), ABC_CC_JSONError, "Error parsing JSON object value"); // get denomination satoshi display size (e.g., 100,000 would be milli-bit coin) pJSON_Value = json_object_get(pJSON_Denom, JSON_ACCT_SATOSHI_FIELD); ABC_CHECK_ASSERT((pJSON_Value && json_is_integer(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON integer value"); pSettings->bitcoinDenomination.satoshi = json_integer_value(pJSON_Value); // get denomination type pJSON_Value = json_object_get(pJSON_Denom, JSON_ACCT_LABEL_TYPE); ABC_CHECK_ASSERT((pJSON_Value && json_is_integer(pJSON_Value)), ABC_CC_JSONError, "Error parsing JSON integer value"); pSettings->bitcoinDenomination.denominationType = json_integer_value(pJSON_Value); // get the exchange rates array json_t *pJSON_Sources = json_object_get(pJSON_Root, JSON_ACCT_EX_RATE_SOURCES_FIELD); ABC_CHECK_ASSERT((pJSON_Sources && json_is_array(pJSON_Sources)), ABC_CC_JSONError, "Error parsing JSON array value"); // get the number of elements in the array pSettings->exchangeRateSources.numSources = (int) json_array_size(pJSON_Sources); if (pSettings->exchangeRateSources.numSources > 0) { ABC_ARRAY_NEW(pSettings->exchangeRateSources.aSources, pSettings->exchangeRateSources.numSources, tABC_ExchangeRateSource*); }