Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenCAP sending feature added #409

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
25 changes: 24 additions & 1 deletion src/js/controllers/tab-send.controller.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

angular.module('copayApp.controllers').controller('tabSendController', function(bitcoinUriService, $scope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, walletService, platformInfo, sendFlowService, gettextCatalog, configService, $ionicPopup, $ionicNavBarDelegate, clipboardService, incomingDataService) {
angular.module('copayApp.controllers').controller('tabSendController', function(bitcoinUriService, $scope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, walletService, platformInfo, sendFlowService, gettextCatalog, configService, $ionicPopup, $ionicNavBarDelegate, clipboardService, incomingDataService, ionicToast, opencapService) {
var clipboardHasAddress = false;
var clipboardHasContent = false;
var originalList;
Expand Down Expand Up @@ -61,6 +61,29 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
});
});

$scope.sendToAlias = function(alias) {
opencapService.get(alias, $scope.fromWallet.coin)
.then(result => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now : => : lambda expression is not supported for old javascript engine.
Should be :

function onThen() {
}

let msg = `${$scope.fromWallet.coin} address found! Address is secure`;
if(!result.dnssec){
msg = `${$scope.fromWallet.coin} address found! Address doesn\'t have maximum DNS security`;
}

let msgTime = 1000;
$scope.$apply(function () {
ionicToast.show(msg, 'bottom', false, msgTime);
});
setTimeout(function(){
$scope.findContact(result.address);
}, msgTime);
})
.catch(status => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now : => : lambda expression is not supported for old javascript engine.
Should be :

function onCatch() {
}

$scope.$apply(function () {
ionicToast.show(status, 'bottom', false, 1500);
});
});
}

$scope.findContact = function(search) {
if (!search || search.length < 1) {
$scope.list = originalList;
Expand Down
160 changes: 160 additions & 0 deletions src/js/services/opencapService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
'use strict';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Your service doesn't follow our standards.
    https://github.com/Bitcoin-com/Wallet/blob/master/src/js/services/shapeshift.service.js
    The link below is an example of our standard for a service.
  2. If you want to use a promise, use the promise from Angular1 provided by $q.
    Example
    var deferred = $q.defer(); ... deferred.resolve(res); deferred.reject(err); ... return deferred.promise;
  3. If you want make a http request, please use $http from Angular1 instead of fetch.
  4. file naming convention opencap.service.js
  5. declare your module in bitcoincom.services

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect. I'll work on this, thanks!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just finished the update. I covered all of your points, let me know if there is anything else you want changed!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I will review it and let you know. I don't guarantee anything, I will review technically if it is suitable to our app.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I'll keep an eye if you need more changes made.


angular.module('copayApp.services').service('opencapService', function () {

function getAddressCall(host, alias, dnssec, coin) {
var callback = function () {
return fetch(
`https://${host}/v1/addresses?alias=${alias}`,
{
method: "GET"
},
"application/json"
);
};

return new Promise((resolve, reject) => {
callback()
.then(parseJSON)
.then(response => {
if (response.ok) {
if (typeof response.body === "undefined") {
return reject('Error contacting opencap server, no data')
}

for (var i = 0; i < response.body.length; i++) {
if (response.body[i].address_type === "undefined") {
continue
}
if (response.body[i].address === "undefined") {
continue
}
if (coin == 'bch' &&
(response.body[i].address_type == 200 ||
response.body[i].address_type == 201)) {
return resolve({ address: response.body[i].address, dnssec })
}
if (coin == 'btc' &&
(response.body[i].address_type == 100 ||
response.body[i].address_type == 101)) {
return resolve({ address: response.body[i].address, dnssec })
}
}

return reject('Error contacting opencap server, no response');
}

return reject('Error contacting opencap server, bad response');
})
.catch(error =>
reject(error.message)
);
});
}

function getAliasData(domain, alias, coin) {
var callback = function () {
return fetch(
`https://dns.google.com/resolve?name=_opencap._tcp.${domain}&type=SRV`,
{
method: "GET"
},
"application/json"
);
};

return callback()
.then(parseJSON)
.then(response => {
return new Promise((resolve, reject) => {
if (response.ok) {
if (typeof response.body.AD === "undefined") {
return reject('Error contacting google dns server, no dnnssec data')
}
let dnssec = response.body.AD;

if (typeof response.body.Answer === "undefined") {
return reject('Error contacting google dns server, no srv data')
}
if (response.body.Answer.length < 1) {
return reject('Error contacting google dns server, not enough srv data')
}

let record = response.body.Answer[0].data.split(' ')
if (record.length != 4) {
return reject('Error contacting google dns server, improper srv data')
}

if (record[3].slice(-1) == '.') {
record[3] = record[3].substring(0, record[3].length - 1);
}

return resolve({ target: record[3], alias, dnssec })
}

return reject('Error contacting google dns server, bad response');
});
})
.then(args =>
getAddressCall(args.target, args.alias, args.dnssec, coin)
)
.catch(function (error) {
return new Promise((resolve, reject) => {
reject(error)
})
})
}

function parseJSON(response) {
return new Promise(resolve =>
response.json().then(json =>
resolve({
status: response.status,
ok: response.ok,
body: json,
})
)
);
}

function validateUsername(username) {
return /^[a-z0-9._-]{1,25}$/.test(username);
}

function validateDomain(username) {
return /^[a-z0-9.\-]+\.[a-z]{2,4}$/.test(username);
}

function validateAlias(alias) {
let splitAlias = alias.split('$');
if (splitAlias.length != 2) {
return { username: '', domain: '' }
}
let username = splitAlias[0];
let domain = splitAlias[1];

if (!validateUsername(username)) {
return { username: '', domain: '' }
}
if (!validateDomain(domain)) {
return { username: '', domain: '' }
}

return { username, domain }
}

function get(alias, coin) {
let aliasData = validateAlias(alias)
if (aliasData.username === '' || aliasData.domain === '') {
return new Promise((resolve, reject) => {
return reject('Invalid OpenCAP alias')
})
}

return getAliasData(aliasData.domain, alias, coin)
}

return {
get,
};
});
14 changes: 14 additions & 0 deletions www/views/tab-send.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ <h2>{{fromWallet.name}}</h2>
</button>
</div>
</div>
<br/>
<div class="row" ng-if="fromWallet">
<div class="col-80">
<div class="input" ng-class="{'focus': searchFocus}">
<input type="text" class="search-input" placeholder="{{'Or send to an alias' | translate}}" ng-model="formData.alias"
ng-model-onblur>
</div>
</div>
<div class="col-20">
<button class="button button-standard button-primary button-outline" ng-click="sendToAlias(formData.alias)">
<span class="non-address" translate>Send to Alias</span>
</button>
</div>
</div>
</div>
</div>

Expand Down